API reference

Core

This module defines Circuit and the setting for circuit. Modernized for PyTorch Tensor Network backend integration in 2026.

class blueqat.circuit.Circuit(n_qubits=0, ops=None)[source]

Store the gate operations and call the backends.

Parameters:
copy(copy_backends=True)[source]

Copy the circuit.

Parameters:

copy_backends (bool)

Return type:

Circuit

dagger(ignore_measurement=False)[source]

Make Hermitian conjugate of the circuit.

If the circuit contains measurement or reset (which have no Hermitian conjugate), ValueError is raised, unless ignore_measurement is True, in which case those operations are simply dropped.

Parameters:

ignore_measurement (bool)

Return type:

Circuit

run(backend=None, *args, **kwargs)[source]

Run the circuit. Passes parameters to the PyTorch-based backend.

Beyond the backend’s own arguments (shots, returns, mode, hamiltonian, amplitude, initial, …), two arguments shape sampled results:

seed

Fix every random draw of this run – shot sampling, mid-circuit collapse and large-n perfect sampling – so that the same circuit and seed give the same counts. It drives a private torch.Generator, leaving the global RNG untouched.

bit_order

Layout of the counts keys: 'q0_last' (the default, and blueqat’s long-standing order, where key[-1] is qubit 0) or 'q0_first', where key[i] is qubit i, as cloud APIs report it. Keys are zero-padded to n_qubits in either order.

Parameters:

backend (str | None)

Return type:

Any

to_qasm(output_prologue=True)[source]

Convert this circuit into an OpenQASM 2.0 program string.

Parameters:

output_prologue (bool)

Return type:

str

statevector(backend=None, bit_order='q0_last', **kwargs)[source]

Run the circuit and get a statevector as a PyTorch Tensor to keep gradients intact.

Amplitude v[k] belongs to the basis state whose qubit q is bit q of k – qubit 0 is the least-significant bit of the index, the same convention as everywhere else in the SDK and as blueqat.BIT_ORDER reports. So for two qubits the order is |00>, |01> with qubit 0 set, |10> with qubit 1 set, |11>.

Reading it the other way round is a mistake nothing catches: it gives the mirror image of the answer, and on a symmetric state – a GHZ, a W, anything permutation-invariant – the two agree, so it can go unnoticed through a whole set of examples and fail on the one that is not symmetric.

bit_order=’q0_first’ puts qubit 0 in the most-significant bit instead, as some other toolkits do. It is the same argument name and the same values that run(shots=…) and probs() take. Having it on some of the three and not the others is itself the trap, because then “I checked with run()” stops being an answer about the other two – and before this it was worse than absent here: the argument was accepted, validated, and then silently ignored, so asking for the other convention returned the default one with nothing said.

Parameters:
  • backend (BackendUnion)

  • bit_order (str)

Return type:

Tensor

shots(shots, backend=None, **kwargs)[source]

Run the circuit and get shot counts as a result.

Accepts the same seed and bit_order arguments as run().

Parameters:
  • shots (int)

  • backend (BackendUnion)

Return type:

Counter[str]

oneshot(backend=None, **kwargs)[source]

Run the circuit once and return the post-measurement statevector together with the single measured bitstring.

Parameters:

backend (BackendUnion)

Return type:

Tuple[Tensor, str]

depth()[source]

Circuit depth: length of the longest gate sequence on any qubit path, counting each expanded gate application (as in Qiskit). Barriers don’t add depth.

Return type:

int

count_ops()[source]

Count expanded gate applications by name (as in Qiskit’s count_ops).

Return type:

Counter[str]

probs(qubits=None, backend=None, bit_order='q0_last', **kwargs)[source]

Measurement probabilities of the circuit’s final state, optionally marginalized onto qubits (as in PennyLane’s qml.probs).

Returns a tensor of length 2**len(qubits). By default index bit j is the outcome of qubits[j]: the first listed qubit is the least-significant bit of the index, matching the SDK-wide convention and what blueqat.BIT_ORDER reports. Differentiable.

bit_order=’q0_first’ reverses that, putting the first listed qubit in the most-significant bit, which is what some other toolkits do. The name and the values are the same ones run(shots=…) takes, so the two do not have to be remembered separately.

Under noise there is no statevector to square; the probabilities are the density matrix’s diagonal, and are read from there.

Parameters:
  • qubits (Sequence[int] | None)

  • backend (BackendUnion)

  • bit_order (str)

Return type:

Tensor

expect(hamiltonian, backend=None, **kwargs)[source]

Expectation value <psi|H|psi> of a Pauli-expression Hamiltonian on the circuit’s final state. Differentiable.

A Hamiltonian is a Pauli expression – Z[0] + 0.5 * X[1], built from the operators exported at the top level – or a string ("Z[0] + 0.5*X[1]"). A dict of coefficients is not one, and neither is a matrix.

The circuit may be narrower than the Hamiltonian: qubits the circuit never mentions are in |0>, which is a perfectly good state to take an expectation in, and Circuit().expect(Z[0]) == 1 rather than an error about a zero-qubit state.

Parameters:
  • hamiltonian (Any)

  • backend (BackendUnion)

Return type:

Tensor

exp_pauli(paulis, theta)[source]

Append exp(-i * theta * P), the time evolution of a single Pauli product.

paulis maps a qubit index to its Pauli letter, so the operator is stated without reference to any bit order or overall width:

Circuit().exp_pauli({0: 'X', 1: 'X', 2: 'Z', 3: 'Y'}, 0.3)  # exp(-0.3i XXZY)

Since P**2 == I, this is exactly cos(theta) - i sin(theta) P. The convention (no factor of 1/2) matches get_time_evolution(); note that a single-qubit {q: 'Z'} is therefore rz(2 * theta)[q].

theta may be a torch.Tensor, in which case the gradient flows through. Letters are case-insensitive, and 'I' entries are ignored. A product of nothing but identities is a global phase, which a statevector does not carry, so it appends no gates.

Parameters:
Return type:

Circuit

block(name)[source]

Group the operations appended inside the with body into a named, nestable block (as in the sub-circuits of Shor’s algorithm):

c = Circuit(4)
with c.block("QFT"):
    c.h[0].cphase(math.pi / 2)[0, 1]
    ...

Blocks change nothing about execution – every backend transparently sees the inner gates – but the structure is kept in repr(), Circuit.tree(), and survives dagger() (as a mirrored block named name + ‘†’).

Parameters:

name (str)

Return type:

_BlockContext

append_block(name, subcircuit, offset=0)[source]

Append an existing circuit as a named block.

offset shifts every qubit index of subcircuit, so a library circuit built on qubits 0..k can be placed anywhere. Shifting resolves slice targets against subcircuit.n_qubits and preserves any nested block structure inside subcircuit.

Parameters:
Return type:

Circuit

tree()[source]

A text rendering of the circuit’s nested block structure:

Circuit(4)
├─ h[0]
└─ QFT
   ├─ cphase(1.5708)[0, 1]
   └─ ...

Blocks appear by name with their contents beneath them; plain gates outside any block are listed at the top level.

Return type:

str

ancilla(n=1, pos=None, stop=None, reset=True)[source]

Context manager allocating temporary ancilla qubit(s) for use inside the with block.

By default, appends n fresh qubits past the circuit’s current width:

with c.ancilla() as a:

c.cx[0, a[0]]

pos/stop instead pin the ancilla range to specific qubit indices (range(pos, stop); stop defaults to pos + n):

with c.ancilla(pos=4, stop=6, reset=True) as a:

c.cx[3, a[0]]

If reset is true (the default), a reset gate is appended for each ancilla qubit on exiting the block, so they’re back at |0> and safe to reuse elsewhere in the circuit.

Parameters:
Return type:

_AncillaContext

class blueqat.circuit.BlueqatGlobalSetting[source]

Setting for Blueqat.

static register_macro(name, func, allow_overwrite=False)[source]

Register new macro to Circuit.

Parameters:
Return type:

None

static unregister_macro(name)[source]

Unregister a macro.

Parameters:

name (str)

Return type:

None

static register_gate(name, gateclass, allow_overwrite=False)[source]

Register new gate to gate set.

Parameters:
Return type:

None

static unregister_gate(name)[source]

Unregister a gate from gate set.

Parameters:

name (str)

Return type:

None

static register_backend(name, backend, allow_overwrite=False)[source]

Register new backend.

Parameters:
Return type:

None

static unregister_backend(name)[source]

Unregister a backend.

Parameters:

name (str)

Return type:

None

static set_default_backend(name)[source]

Set the default backend to be used by Circuit.

Parameters:

name (str)

Return type:

None

static get_default_backend_name()[source]

Get the default backend name.

Return type:

str

gate module implements quantum gate operations. Modernized for PyTorch Tensor Network integration in 2026.

class blueqat.gate.Operation(targets, params=())[source]

Abstract quantum circuit operation class.

Parameters:

targets (int | slice | tuple | list | Tensor)

lowername: str = ''

Lower name of the operation.

property uppername: str

Upper name of the operation.

target_iter(n_qubits)[source]

The generator which yields the target qubits.

Parameters:

n_qubits (int)

Return type:

Iterator[int]

classmethod create(targets, params, options)[source]

Create an operation.

Parameters:
Return type:

_Op

class blueqat.gate.IFallbackOperation(targets, params=())[source]

The interface of fallback

Parameters:

targets (int | slice | tuple | list | Tensor)

fallback(n_qubits)[source]

Get alternative operations

Parameters:

n_qubits (int)

Return type:

List[Operation]

class blueqat.gate.Gate(targets, params=())[source]

Abstract quantum gate class.

Parameters:

targets (int | slice | tuple | list | Tensor)

property n_qargs: int

Number of qubit arguments of this gate.

dagger()[source]

Returns the Hermitian conjugate of self.

Return type:

Gate

matrix()[source]

Returns the matrix of implementations as a PyTorch Tensor.

Return type:

Tensor

class blueqat.gate.OneQubitGate(targets, params=())[source]

Abstract quantum gate class for 1 qubit gate.

Parameters:

targets (int | slice | tuple | list | Tensor)

property n_qargs: int

Number of qubit arguments of this gate.

class blueqat.gate.TwoQubitGate(targets, params=())[source]

Abstract quantum gate class for 2 qubits gate.

Parameters:

targets (int | slice | tuple | list | Tensor)

property n_qargs

Number of qubit arguments of this gate.

control_target_iter(n_qubits)[source]

The generator which yields the tuples of (control, target) qubits.

Parameters:

n_qubits (int)

Return type:

Iterator[Tuple[int, int]]

class blueqat.gate.HGate(targets, params=())[source]

Hadamard gate

Parameters:

targets (int | slice | tuple | list | Tensor)

lowername: str = 'h'

Lower name of the operation.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

HGate

dagger()[source]

Returns the Hermitian conjugate of self.

matrix()[source]

Returns the matrix of implementations as a PyTorch Tensor.

class blueqat.gate.IGate(targets, params=())[source]

Identity gate

Parameters:

targets (int | slice | tuple | list | Tensor)

lowername: str = 'i'

Lower name of the operation.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

IGate

fallback(_)[source]

Get alternative operations

dagger()[source]

Returns the Hermitian conjugate of self.

matrix()[source]

Returns the matrix of implementations as a PyTorch Tensor.

class blueqat.gate.Mat1Gate(targets, mat)[source]

Arbitrary 2x2 matrix gate

Parameters:

mat (Tensor)

lowername: str = 'mat1'

Lower name of the operation.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

Mat1Gate

dagger()[source]

Returns the Hermitian conjugate of self.

matrix()[source]

Returns the matrix of implementations as a PyTorch Tensor.

class blueqat.gate.PhaseGate(targets, theta)[source]

Phase gate

lowername: str = 'phase'

Lower name of the operation.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

PhaseGate

dagger()[source]

Returns the Hermitian conjugate of self.

matrix()[source]

Returns the matrix of implementations as a PyTorch Tensor.

class blueqat.gate.RXGate(targets, theta)[source]

Rotate-X gate

lowername: str = 'rx'

Lower name of the operation.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

RXGate

dagger()[source]

Returns the Hermitian conjugate of self.

matrix()[source]

Returns the matrix of implementations as a PyTorch Tensor.

class blueqat.gate.RYGate(targets, theta)[source]

Rotate-Y gate

lowername: str = 'ry'

Lower name of the operation.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

RYGate

dagger()[source]

Returns the Hermitian conjugate of self.

matrix()[source]

Returns the matrix of implementations as a PyTorch Tensor.

class blueqat.gate.RZGate(targets, theta)[source]

Rotate-Z gate

lowername: str = 'rz'

Lower name of the operation.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

RZGate

dagger()[source]

Returns the Hermitian conjugate of self.

matrix()[source]

Returns the matrix of implementations as a PyTorch Tensor.

class blueqat.gate.SGate(targets, params=())[source]

S gate

Parameters:

targets (int | slice | tuple | list | Tensor)

lowername: str = 's'

Lower name of the operation.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

SGate

dagger()[source]

Returns the Hermitian conjugate of self.

fallback(n_qubits)[source]

Get alternative operations

matrix()[source]

Returns the matrix of implementations as a PyTorch Tensor.

class blueqat.gate.SDagGate(targets, params=())[source]

Dagger of S gate

Parameters:

targets (int | slice | tuple | list | Tensor)

lowername: str = 'sdg'

Lower name of the operation.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

SDagGate

dagger()[source]

Returns the Hermitian conjugate of self.

fallback(n_qubits)[source]

Get alternative operations

matrix()[source]

Returns the matrix of implementations as a PyTorch Tensor.

class blueqat.gate.SXGate(targets, params=())[source]

sqrt(X) gate

Parameters:

targets (int | slice | tuple | list | Tensor)

lowername: str = 'sx'

Lower name of the operation.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

SXGate

dagger()[source]

Returns the Hermitian conjugate of self.

matrix()[source]

Returns the matrix of implementations as a PyTorch Tensor.

class blueqat.gate.SXDagGate(targets, params=())[source]

sqrt(X)† gate

Parameters:

targets (int | slice | tuple | list | Tensor)

lowername: str = 'sxdg'

Lower name of the operation.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

SXDagGate

dagger()[source]

Returns the Hermitian conjugate of self.

matrix()[source]

Returns the matrix of implementations as a PyTorch Tensor.

class blueqat.gate.TGate(targets, params=())[source]

T gate

Parameters:

targets (int | slice | tuple | list | Tensor)

lowername: str = 't'

Lower name of the operation.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

TGate

dagger()[source]

Returns the Hermitian conjugate of self.

fallback(_)[source]

Get alternative operations

matrix()[source]

Returns the matrix of implementations as a PyTorch Tensor.

class blueqat.gate.TDagGate(targets, params=())[source]

Dagger of T gate

Parameters:

targets (int | slice | tuple | list | Tensor)

lowername: str = 'tdg'

Lower name of the operation.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

TDagGate

dagger()[source]

Returns the Hermitian conjugate of self.

fallback(_)[source]

Get alternative operations

matrix()[source]

Returns the matrix of implementations as a PyTorch Tensor.

class blueqat.gate.ToffoliGate(targets, params=())[source]

Toffoli (CCX) gate

Parameters:

targets (int | slice | tuple | list | Tensor)

lowername: str = 'ccx'

Lower name of the operation.

property n_qargs

Number of qubit arguments of this gate.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

ToffoliGate

dagger()[source]

Returns the Hermitian conjugate of self.

fallback(n_qubits)[source]

Get alternative operations

matrix()[source]

Returns the matrix of implementations as a PyTorch Tensor.

class blueqat.gate.UGate(targets, theta, phi, lam, gamma=0.0)[source]

Arbitrary 1 qubit unitary gate

lowername: str = 'u'

Lower name of the operation.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

UGate

dagger()[source]

Returns the Hermitian conjugate of self.

matrix()[source]

Returns the matrix of implementations as a PyTorch Tensor.

class blueqat.gate.XGate(targets, params=())[source]

Pauli’s X gate

Parameters:

targets (int | slice | tuple | list | Tensor)

lowername: str = 'x'

Lower name of the operation.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

XGate

dagger()[source]

Returns the Hermitian conjugate of self.

matrix()[source]

Returns the matrix of implementations as a PyTorch Tensor.

class blueqat.gate.YGate(targets, params=())[source]

Pauli’s Y gate

Parameters:

targets (int | slice | tuple | list | Tensor)

lowername: str = 'y'

Lower name of the operation.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

YGate

dagger()[source]

Returns the Hermitian conjugate of self.

matrix()[source]

Returns the matrix of implementations as a PyTorch Tensor.

class blueqat.gate.ZGate(targets, params=())[source]

Pauli’s Z gate

Parameters:

targets (int | slice | tuple | list | Tensor)

lowername: str = 'z'

Lower name of the operation.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

ZGate

dagger()[source]

Returns the Hermitian conjugate of self.

matrix()[source]

Returns the matrix of implementations as a PyTorch Tensor.

class blueqat.gate.CCZGate(targets, params=())[source]

2-Controlled Z gate

Parameters:

targets (int | slice | tuple | list | Tensor)

lowername: str = 'ccz'

Lower name of the operation.

property n_qargs

Number of qubit arguments of this gate.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

CCZGate

fallback(n_qubits)[source]

Get alternative operations

dagger()[source]

Returns the Hermitian conjugate of self.

matrix()[source]

Returns the matrix of implementations as a PyTorch Tensor.

class blueqat.gate.CHGate(targets, params=())[source]

Controlled-H gate

Parameters:

targets (int | slice | tuple | list | Tensor)

lowername: str = 'ch'

Lower name of the operation.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

CHGate

dagger()[source]

Returns the Hermitian conjugate of self.

matrix()[source]

Returns the matrix of implementations as a PyTorch Tensor.

class blueqat.gate.CPhaseGate(targets, theta)[source]

Controlled Phase gate

lowername: str = 'cphase'

Lower name of the operation.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

CPhaseGate

dagger()[source]

Returns the Hermitian conjugate of self.

matrix()[source]

Returns the matrix of implementations as a PyTorch Tensor.

class blueqat.gate.CRXGate(targets, theta)[source]

Controlled RX gate

lowername: str = 'crx'

Lower name of the operation.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

CRXGate

dagger()[source]

Returns the Hermitian conjugate of self.

matrix()[source]

Returns the matrix of implementations as a PyTorch Tensor.

class blueqat.gate.CRYGate(targets, theta)[source]

Controlled RY gate

lowername: str = 'cry'

Lower name of the operation.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

CRYGate

dagger()[source]

Returns the Hermitian conjugate of self.

matrix()[source]

Returns the matrix of implementations as a PyTorch Tensor.

class blueqat.gate.CRZGate(targets, theta)[source]

Controlled RZ gate

lowername: str = 'crz'

Lower name of the operation.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

CRZGate

dagger()[source]

Returns the Hermitian conjugate of self.

matrix()[source]

Returns the matrix of implementations as a PyTorch Tensor.

class blueqat.gate.CSwapGate(targets, params=())[source]

Controlled SWAP gate

Parameters:

targets (int | slice | tuple | list | Tensor)

lowername: str = 'cswap'

Lower name of the operation.

property n_qargs

Number of qubit arguments of this gate.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

CSwapGate

dagger()[source]

Returns the Hermitian conjugate of self.

fallback(n_qubits)[source]

Get alternative operations

matrix()[source]

Returns the matrix of implementations as a PyTorch Tensor.

class blueqat.gate.CUGate(targets, theta, phi, lam, gamma=0.0)[source]

Controlled-U gate

lowername: str = 'cu'

Lower name of the operation.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

CUGate

dagger()[source]

Returns the Hermitian conjugate of self.

matrix()[source]

Returns the matrix of implementations as a PyTorch Tensor.

class blueqat.gate.CXGate(targets, params=())[source]

Controlled-X (CNOT) gate

Parameters:

targets (int | slice | tuple | list | Tensor)

lowername: str = 'cx'

Lower name of the operation.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

CXGate

dagger()[source]

Returns the Hermitian conjugate of self.

matrix()[source]

Returns the matrix of implementations as a PyTorch Tensor.

class blueqat.gate.CYGate(targets, params=())[source]

Controlled-Y gate

Parameters:

targets (int | slice | tuple | list | Tensor)

lowername: str = 'cy'

Lower name of the operation.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

CYGate

dagger()[source]

Returns the Hermitian conjugate of self.

matrix()[source]

Returns the matrix of implementations as a PyTorch Tensor.

class blueqat.gate.CZGate(targets, params=())[source]

Controlled-Z gate

Parameters:

targets (int | slice | tuple | list | Tensor)

lowername: str = 'cz'

Lower name of the operation.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

CZGate

dagger()[source]

Returns the Hermitian conjugate of self.

matrix()[source]

Returns the matrix of implementations as a PyTorch Tensor.

class blueqat.gate.RXXGate(targets, theta)[source]

Rotate-XX gate

lowername: str = 'rxx'

Lower name of the operation.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

RXXGate

dagger()[source]

Returns the Hermitian conjugate of self.

matrix()[source]

Returns the matrix of implementations as a PyTorch Tensor.

class blueqat.gate.RYYGate(targets, theta)[source]

Rotate-YY gate

lowername: str = 'ryy'

Lower name of the operation.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

RYYGate

dagger()[source]

Returns the Hermitian conjugate of self.

matrix()[source]

Returns the matrix of implementations as a PyTorch Tensor.

class blueqat.gate.RZZGate(targets, theta)[source]

Rotate-ZZ gate

lowername: str = 'rzz'

Lower name of the operation.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

RZZGate

dagger()[source]

Returns the Hermitian conjugate of self.

matrix()[source]

Returns the matrix of implementations as a PyTorch Tensor.

class blueqat.gate.SwapGate(targets, params=())[source]

Swap gate

Parameters:

targets (int | slice | tuple | list | Tensor)

lowername: str = 'swap'

Lower name of the operation.

dagger()[source]

Returns the Hermitian conjugate of self.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

SwapGate

matrix()[source]

Returns the matrix of implementations as a PyTorch Tensor.

class blueqat.gate.ZZGate(targets)[source]

ZZ gate

lowername: str = 'zz'

Lower name of the operation.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

ZZGate

dagger()[source]

Returns the Hermitian conjugate of self.

matrix()[source]

Returns the matrix of implementations as a PyTorch Tensor.

class blueqat.gate.ZZDagGate(targets)[source]

Dagger of ZZ gate

lowername: str = 'zzdg'

Lower name of the operation.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

ZZDagGate

dagger()[source]

Returns the Hermitian conjugate of self.

matrix()[source]

Returns the matrix of implementations as a PyTorch Tensor.

class blueqat.gate.ISwapGate(targets, params=())[source]

iSWAP gate: swaps two qubits and phases the swapped amplitudes by i.

Parameters:

targets (int | slice | tuple | list | Tensor)

lowername: str = 'iswap'

Lower name of the operation.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

ISwapGate

dagger()[source]

Returns the Hermitian conjugate of self.

fallback(n_qubits)[source]

Get alternative operations

matrix()[source]

Returns the matrix of implementations as a PyTorch Tensor.

class blueqat.gate.ISwapDagGate(targets, params=())[source]

Dagger of iSWAP gate.

Parameters:

targets (int | slice | tuple | list | Tensor)

lowername: str = 'iswapdg'

Lower name of the operation.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

ISwapDagGate

dagger()[source]

Returns the Hermitian conjugate of self.

fallback(n_qubits)[source]

Get alternative operations

matrix()[source]

Returns the matrix of implementations as a PyTorch Tensor.

class blueqat.gate.ExchangeGate(targets, theta)[source]

Heisenberg exchange pulse, the native primitive of exchange-only (EO) spin-qubit hardware: U(theta) = exp(-i theta/2 (SWAP - I)), i.e. identity on the triplet (symmetric) subspace and phase e^{i theta} on the singlet.

theta = J*t is the integrated pulse area (exchange integral x duration); theta = pi gives an exact SWAP, theta = pi/2 a sqrt-SWAP up to phase. Symmetric in its two qubits.

lowername: str = 'exch'

Lower name of the operation.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

ExchangeGate

dagger()[source]

Returns the Hermitian conjugate of self.

fallback(n_qubits)[source]

Get alternative operations

matrix()[source]

Returns the matrix of implementations as a PyTorch Tensor.

class blueqat.gate.Barrier(targets, params=())[source]

Barrier: a no-op marker separating circuit sections (as in Qiskit and OpenQASM). Simulation backends treat it as the identity via its empty fallback; the QASM output backend emits a real barrier statement.

Parameters:

targets (int | slice | tuple | list | Tensor)

lowername: str = 'barrier'

Lower name of the operation.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

Barrier

fallback(_)[source]

Get alternative operations

dagger()[source]
class blueqat.gate.GateBlock(name, ops=None)[source]

A named group of operations, nestable to arbitrary depth.

Blocks give circuits the hierarchical structure of real algorithms (Shor = init + modular exponentiation + inverse QFT, each built from smaller blocks) without changing how they execute: every backend sees the inner operations through fallback(), so simulation, QASM output and transpilation are unaffected. The structure shows up in repr() and in Circuit.tree().

Build blocks with Circuit.block(name) (a context manager) or Circuit.append_block(name, subcircuit).

Parameters:
lowername: str = 'block'

Lower name of the operation.

ops: List[Operation]
classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

GateBlock

fallback(_)[source]

Get alternative operations

dagger()[source]
target_iter(n_qubits)[source]

The generator which yields the target qubits.

Parameters:

n_qubits (int)

class blueqat.gate.Measurement(targets, options)[source]

Measurement operation

Parameters:
lowername: str = 'measure'

Lower name of the operation.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

Measurement

target_iter(n_qubits)[source]

The generator which yields the target qubits.

class blueqat.gate.Reset(targets, params=())[source]

Reset operation

Parameters:

targets (int | slice | tuple | list | Tensor)

lowername: str = 'reset'

Lower name of the operation.

classmethod create(targets, params, options=None)[source]

Create an operation.

Parameters:
Return type:

Reset

target_iter(n_qubits)[source]

The generator which yields the target qubits.

blueqat.gate.find_n_qubits(gates)[source]
Parameters:

gates (Iterable[Operation])

Return type:

int

Pauli operators, VQE and QAOA

Integrated Quantum Operators, Utilities, VQE, and QAOA module with PyTorch. Refactored and merged into a unified utils.py module with robust Autograd tracking.

class blueqat.utils.Term(ops, coeff)[source]
static from_paulipair(pauli1, pauli2)[source]
Parameters:
Return type:

Term

static from_pauli(pauli, coeff=1.0)[source]
Parameters:
Return type:

Term

static from_ops_iter(ops, coeff)[source]
Parameters:
Return type:

Term

static from_chars(chars)[source]
Parameters:

chars (Any)

Return type:

Term

static join_ops(ops1, ops2)[source]
Parameters:
Return type:

tuple

property is_identity: bool
to_term()[source]
Return type:

Term

to_expr()[source]
Return type:

Expr

simplify()[source]
Return type:

Term

n_iter()[source]
Return type:

Iterator[int]

max_n()[source]
Return type:

int

property n_qubits: int
is_commutable_with(other)[source]
Parameters:

other (Any)

Return type:

bool

get_time_evolution()[source]

Returns a function f(circuit, t) appending exp(-i t P) to circuit, where P = coeff * (this term’s Pauli product). Requires a real coefficient (a complex one would make the “evolution” non-unitary).

Return type:

Any

to_matrix(n_qubits=-1, *, sparse=False, device=None)[source]
Parameters:
  • n_qubits (int)

  • sparse (bool)

  • device (device | None)

Return type:

Tensor

class blueqat.utils.Expr(terms)[source]
static from_number(num)[source]
Parameters:

num (Any)

Return type:

Expr

static from_term(term)[source]
Parameters:

term (Term)

Return type:

Expr

static from_terms_iter(terms)[source]
Parameters:

terms (Any)

Return type:

Expr

terms_to_dict()[source]
Return type:

dict

static from_terms_dict(terms_dict)[source]
Parameters:

terms_dict (dict)

Return type:

Expr

static zero()[source]
Return type:

Expr

property is_identity: bool
to_expr()[source]
Return type:

Expr

max_n()[source]
Return type:

int

is_commutable_with(other)[source]
Parameters:

other (Any)

Return type:

bool

is_all_terms_commutable()[source]
Return type:

bool

property n_qubits: int
coeffs()[source]
Return type:

Iterator[Any]

simplify()[source]
Return type:

Expr

to_matrix(n_qubits=-1, *, sparse=False, device=None)[source]
Parameters:
  • n_qubits (int)

  • sparse (bool)

  • device (device | None)

Return type:

Tensor

blueqat.utils.pauli_from_char(ch, n=0)[source]
Parameters:
Return type:

_PauliImpl

blueqat.utils.term_from_chars(chars)[source]

Make Pauli’s Term from chars written as ‘X’, ‘Y’, ‘Z’ or ‘I’.

Parameters:

chars (str)

Return type:

Term

blueqat.utils.commutator(expr1, expr2)[source]

Returns [expr1, expr2] = expr1 * expr2 - expr2 * expr1.

Parameters:
Return type:

Expr

blueqat.utils.is_commutable(expr1, expr2, eps=1e-08)[source]

Test whether expr1 and expr2 are commutable.

Parameters:
Return type:

bool

blueqat.utils.parse_hamiltonian(text)[source]

Parse a Pauli-expression string like "1.5*Z[0]*Z[1] - 0.5*X0 + 2" into an Expr, without using eval (safe for untrusted input, e.g. tool calls arriving over MCP).

Grammar: terms joined by +/-; each term is an optional numeric coefficient and a product of Pauli factors X/Y/Z/I with the qubit index written as [n] or directly n. * between factors is optional. A term with no Pauli factor is a constant (times identity).

Parameters:

text (str)

Return type:

Expr

blueqat.utils.qubo_bit(n)[source]
Parameters:

n (int)

Return type:

Expr

blueqat.utils.from_qubo(qubo)[source]
Parameters:

qubo (Sequence[Sequence[float]])

Return type:

Expr

blueqat.utils.to_inttuple(bitstr)[source]
Parameters:

bitstr (str | Counter | Dict[str, int])

Return type:

Tuple[int, …] | Counter | Dict[Tuple[int, …], int]

blueqat.utils.ignore_global_phase(statevec)[source]

Multiply e^-iθ to statevec where θ is a phase of first non-zero element.

Parameters:

statevec (Tensor)

Return type:

Tensor

blueqat.utils.gen_graycode(n)[source]
Parameters:

n (int)

Return type:

Iterator[int]

blueqat.utils.gen_gray_controls(n)[source]

Generate an iterator which returns bit indices for constructing Gray code based controlled gate.

Parameters:

n (int)

Return type:

Iterator[Tuple[int, int, int]]

blueqat.utils.random_unitary(dim, seed=None, device=None)[source]

A dim x dim unitary drawn from the Haar measure.

The usual recipe – QR-decompose a complex Gaussian matrix and take Q – is not Haar distributed on its own, because QR does not fix the phases of Q’s columns. Multiplying by the phases of R’s diagonal is what fixes it, and omitting that step biases the distribution in a way that quietly shifts quantities like the heavy-output probability of a random circuit.

seed uses a private generator and leaves the global RNG alone.

Returns a torch.Tensor, as everything else in this SDK does – call .numpy() on it before mixing with NumPy, or numpy operations will fail on the tensor rather than converting it.

Parameters:
  • dim (int)

  • seed (int | None)

  • device (device | None)

Return type:

Tensor

blueqat.utils.check_unitarity(mat)[source]

Check whether mat is a unitary matrix.

Parameters:

mat (Tensor)

Return type:

bool

blueqat.utils.calc_u_params(mat)[source]

Calculate U-gate parameters from a 2x2 unitary matrix.

U(theta, phi, lam, gamma) is

e^{i gamma} [[cos(t), -e^{i lam} sin(t)], [e^{i phi} sin(t), e^{i(phi+lam)} cos(t)]] with t = theta / 2.

The general route reads gamma off mat[0, 0] and phi + lam off mat[1, 1]. An antidiagonal unitary – X and Y among them – has both of those equal to zero, and cmath.phase(0) returns 0.0 without complaint, so two free phases silently vanish and the reconstructed gate is a different unitary, not merely a different global phase. That case is handled separately below.

Parameters:

mat (Tensor)

Return type:

Tuple[float, float, float, float]

blueqat.utils.sqrt_2x2_matrix(mat)[source]

Returns square root of a 2x2 matrix.

Reference: https://en.wikipedia.org/wiki/Square_root_of_a_2_by_2_matrix

Parameters:

mat (Tensor)

Return type:

Tensor

class blueqat.utils.AnsatzBase(hamiltonian, n_params)[source]

Base class for Variational Quantum Eigensolver Ansatz using PyTorch.

Parameters:
  • hamiltonian (Any)

  • n_params (int)

n_qubits: int
sparse: Tensor | None
make_sparse(sparse=True, device=None)[source]
Parameters:
  • sparse (bool)

  • device (device | None)

Return type:

None

get_circuit(params)[source]
Parameters:

params (Tensor)

Return type:

Circuit

get_energy(circuit, sampler)[source]

Calculate energy expectation value from circuit and sampler with Autograd support.

Whether the result carries a gradient back to circuit’s parameters depends on sampler: an exact sampler (e.g. non_sampling_sampler) keeps the autograd graph intact, while a genuinely stochastic one (e.g. one built from get_measurement_sampler) does not – real shot noise isn’t differentiable, so that is expected, not a bug. To optimize through such a sampler anyway, Vqe estimates the gradient with parameter_shift_gradient instead, which it selects on its own by default.

Parameters:
Return type:

Tensor

get_energy_sparse(circuit)[source]
Parameters:

circuit (Circuit)

Return type:

Tensor

get_objective(sampler=None, device=None)[source]
Parameters:
Return type:

Callable[[Tensor], Tensor]

class blueqat.utils.QaoaAnsatz(hamiltonian, step=1, init_circuit=None, mixer=None)[source]
Parameters:
check_hamiltonian()[source]

Check hamiltonian is commutable. This condition is required for QaoaAnsatz, since get_circuit Trotterizes e^{-iHt} into a per-term product of time evolutions – exact only when every term commutes with every other term.

Return type:

bool

get_circuit(params)[source]
Parameters:

params (Tensor)

Return type:

Circuit

class blueqat.utils.VqeResult(vqe: Optional[ForwardRef('Vqe')] = None, params: Optional[torch.Tensor] = None, circuit: Optional[blueqat.circuit.Circuit] = None, loss_history: List[float] = <factory>, _probs: Optional[Dict[Tuple[int, ...], float]] = None)[source]
Parameters:
vqe: Vqe | None = None
params: Tensor | None = None
circuit: Circuit | None = None
loss_history: List[float]

Objective value at every optimizer iteration, in order, so that a run can be checked for convergence without re-running it with another optimizer. len(loss_history) is the number of iterations actually taken (which is below max_iter when the gradient-norm tolerance stopped the loop early).

most_common(n=1)[source]
Parameters:

n (int)

Return type:

Tuple[Tuple[Tuple[int, …], float], …]

get_probs(sampler=None, rerun=None, store=True)[source]
Parameters:
Return type:

Dict[Tuple[int, …], float]

class blueqat.utils.Vqe(ansatz, optimizer_cls=<class 'torch.optim.adam.Adam'>, optimizer_kwargs=None, sampler=None, seed=None, gradient='auto')[source]
Parameters:
run(max_iter=500, tol=1e-06, verbose=False, device=None, initial_params=None, seed=None, gradient=None)[source]
Parameters:
  • max_iter (int)

  • tol (float)

  • verbose (bool)

  • device (device | None)

  • initial_params (Tensor | None)

  • seed (int | None)

  • gradient (str | None)

Return type:

VqeResult

blueqat.utils.expect(qubits, meas)[source]

Marginal probabilities of meas qubits, as gradient-carrying tensors (not plain floats) so that AnsatzBase.get_energy can backprop through them when qubits came from a differentiable circuit run.

Parameters:
Return type:

Dict[Tuple[int, …], Tensor]

blueqat.utils.non_sampling_sampler(circuit, meas)[source]
Parameters:
Return type:

Dict[Tuple[int, …], float]

blueqat.utils.get_measurement_sampler(n_sample, device=None, seed=None)[source]

A sampler that estimates probabilities from n_sample simulated measurements.

With seed set, the sampler draws from its own generator instead of the global RNG, so a VQE run using it is reproducible. The returned callable also carries a set_seed(seed) method, which is what Vqe.run(seed=…) calls to put the whole run – initial parameters and sampling alike – under a single seed.

Parameters:
  • n_sample (int)

  • device (device | None)

  • seed (int | None)

Return type:

Callable[[Circuit, Iterable[int]], Dict[Tuple[int, …], float]]

blueqat.utils.pauli_expectation(hamiltonian, state, n_qubits=-1)[source]

<psi|H|psi> for a Pauli-expression H, without ever building H as a matrix.

A Pauli product is a signed permutation of basis states, so each term costs one pass over the state. Forming the 2**n x 2**n matrix first – what Expr.to_matrix() does – instead costs 4**n, which puts even 16 qubits out of reach. Differentiable in both the state and tensor-valued coefficients.

state is either a statevector (1-D), giving <psi|H|psi>, or a density matrix (2-D), giving Tr(rho H). n_qubits defaults to the width implied by the state.

Parameters:
  • hamiltonian (Any)

  • state (Tensor)

  • n_qubits (int)

Return type:

Tensor

blueqat.utils.SHIFT_RULE_GATES = frozenset({'cp', 'cphase', 'cr', 'exch', 'exchange', 'p', 'phase', 'r', 'rx', 'rxx', 'ry', 'ryy', 'rz', 'rzz'})

Gates whose generator has exactly two eigenvalues one apart, which is what makes the two-term shift rule exact. Controlled rotations (crx/cry/crz) have four eigenvalues and need a four-term rule, so they are refused rather than silently given a wrong gradient.

blueqat.utils.parameter_shift_gradient(ansatz, params, energy_of_circuit)[source]

The energy and its gradient at params, by the parameter-shift rule.

Backpropagation cannot see through a sampler: estimating an expectation value from shots throws away the autograd graph, so shot-based VQE has no gradient to descend. The shift rule gets one from the same estimator, by evaluating it at shifted parameters instead of differentiating it.

Each gate’s own derivative is (E(theta + pi/2) - E(theta - pi/2)) / 2, exact rather than a finite difference. Those are then chained onto params through autograd, so a parameter feeding several gates – as QAOA’s angles do – correctly sums their contributions.

energy_of_circuit takes a circuit and returns its energy; the cost is two of those evaluations per parametric gate application.

Parameters:
Return type:

Tuple[Tensor, Tensor]

blueqat.utils.sparse_expectation(mat, vec)[source]
Parameters:
  • mat (Tensor)

  • vec (Tensor)

Return type:

Tensor

Backends

Base class and plugin registration system for Blueqat backends.

blueqat.backends.backendbase.BIT_ORDERS: Tuple[str, ...] = ('q0_last', 'q0_first')

Accepted values of the bit_order= argument of Circuit.run(shots=…). “q0_last” is blueqat’s long-standing layout – the leftmost character of a counts key is the highest-numbered qubit, so key[-1] is qubit 0. “q0_first” is the reverse, key[i] is qubit i, matching qapi.blueqat.app and most cloud APIs. Either way the key is exactly n_qubits characters wide.

blueqat.backends.backendbase.apply_bit_order(counts, n_qubits, bit_order='q0_last')[source]

Re-key a shot Counter, whose keys are in blueqat’s own “q0_last” order, into the requested qubit-to-character order.

Keys are zero-padded to exactly n_qubits characters first – which is only correct for “q0_last” input, since that is the order whose padding goes on the left. Without the padding, a reversed “11” cannot be told apart from “000011” (qubits 0 and 1) and “110000” (qubits 4 and 5), which is precisely the mistake that hand-rolled reversals keep making.

Parameters:
Return type:

Counter[str]

class blueqat.backends.backendbase.Backend[source]

Abstract base class for all Blueqat simulation and compilation backends.

run has a default template-method implementation: a backend that doesn’t override run directly can instead define per-gate gate_{lowername}(self, gate, ctx) hook methods (e.g. gate_x, gate_cx), plus optionally _preprocess_run/_postprocess_run to build/consume its own ctx. See QasmOutputBackend for an example. Backends like TorchBackend that need a different execution model override run directly instead.

copy()[source]

Returns a (deep) copy of this backend. Override if a shallower/cheaper copy is valid for a particular backend.

Return type:

Backend

run(gates, n_qubits, *args, **kwargs)[source]

Execute the quantum circuit represented by a list of gates.

Parameters:
Return type:

Any

blueqat.backends.backendbase.register_backend(name, backend_cls, overwrite=False)[source]

Register a new backend plugin dynamically.

This allows external packages (like a quimb or cuQuantum connector) to register themselves into Blueqat at runtime.

Parameters:
Return type:

None

blueqat.backends.backendbase.get_backend(name)[source]

Retrieve an instance of the registered backend by name.

Parameters:

name (str)

Return type:

Backend

Unified Differentiable Quantum Simulator Backend using PyTorch. Supports both pure Statevector and ultra-scalable Tensor Network contraction. Leverages opt_einsum for path optimization while executing fully via PyTorch.

class blueqat.backends.torch_backend.TorchBackend(mode='tensornet', device=None, dtype=None)[source]

Unified PyTorch simulator backend supporting Autograd optimization.

Parameters:
  • mode (str)

  • device (device | None)

  • dtype (dtype | None)

copy()[source]

Return a copy of this backend. TorchBackend keeps no run-to-run cache, so this simply constructs a fresh instance with the same configuration.

Return type:

TorchBackend

run(gates, n_qubits, shots=None, returns=None, **kwargs)[source]

Execute the quantum circuit represented by a list of gates.

Parameters:
Return type:

Any

Exchange-only spin qubits

The 3-spin decoherence-free-subsystem (DFS) encoding of exchange-only qubits.

One logical qubit lives in the total-spin S=1/2 sector of 3 physical spins (spin up = |0>, physical qubit 3i+k is spin k of logical qubit i, qubit 0 is the least-significant statevector bit, as everywhere in this SDK):

|0_L> = |singlet(0,1)> |up(2)> |1_L> = sqrt(2/3) |T+(0,1)> |down(2)> - sqrt(1/3) |T0(0,1)> |up(2)>

Each logical state comes in two “gauge” copies, the total-Sz m=+1/2 sector above and its m=-1/2 partner; exchange acts identically on both, and any population in the fully symmetric S=3/2 quadruplet is leakage.

blueqat.eo.encoding.codeword_basis(m='+')[source]

(8, 2) matrix whose columns are |0_L>, |1_L> of the requested gauge sector (‘+’ for total Sz = +1/2, ‘-’ for -1/2).

Parameters:

m (str)

Return type:

Tensor

blueqat.eo.encoding.encode_state(logical_amplitudes, m='+')[source]

Encode a product state of logical qubits into 3n physical spins.

logical_amplitudes[i] is the (alpha, beta) pair of logical qubit i. Returns the 2**(3n) statevector (logical qubit 0’s spins are physical qubits 0..2, i.e. the least-significant bits).

Parameters:
Return type:

Tensor

blueqat.eo.encoding.leakage(state, triple=0)[source]

Population outside the S=1/2 subspace of the given 3-spin triple, i.e. the weight in its fully symmetric S=3/2 quadruplet.

state is either a statevector (1-D) or a density matrix (2-D), so leakage can be read off a noisy run as well as a pure one – which is the case that matters, since it is decoherence that pushes population out of the encoded subspace in the first place.

Parameters:
  • state (Tensor)

  • triple (int)

Return type:

float

blueqat.eo.encoding.logical_action(unitary8, m='+', atol=1e-09)[source]

Extract the 2x2 logical action of a 3-spin (8x8) unitary.

Raises ValueError if the unitary leaks out of the logical subspace of the requested gauge sector (the extracted block would then be non-unitary).

Parameters:
  • unitary8 (Tensor)

  • m (str)

  • atol (float)

Return type:

Tensor

blueqat.eo.encoding.logical_fidelity(actual, target)[source]

Phase-insensitive gate fidelity |tr(A^dagger T)|^2 / d^2 of two equally-sized unitaries.

Parameters:
  • actual (Tensor)

  • target (Tensor)

Return type:

float

blueqat.eo.encoding.two_qubit_codeword_basis(m1, m2)[source]

(64, 4) basis of a 2-logical-qubit (6-spin) sector: columns are |00_L>, |01_L>, |10_L>, |11_L> with gauge m1 for logical qubit 0 (spins 0-2) and m2 for logical qubit 1 (spins 3-5).

Parameters:
Return type:

Tensor

blueqat.eo.encoding.two_qubit_logical_action(unitary64, m1='+', m2='+', atol=1e-09)[source]

Extract the 4x4 logical action of a 6-spin unitary on the encoded pair.

Parameters:
Return type:

Tensor

Analytic exchange-pulse sequences for logical gates on encoded EO qubits.

A sequence is a list of ((i, j), theta) pairs in application order, where (i, j) are physical spin indices within the logical qubits involved and theta is the exchange pulse area for Circuit().exch(theta)[i, j]. All logical gates are exact up to a global phase.

Single-qubit tables and the serial Fong-Wandzura CNOT follow the constant- amplitude constructions used in eoqrid (MIT, https://github.com/samn33/eoqrid) and Weinstein et al., Nature 615, 817 (2023); the CNOT runs on the 6-spin linear chain t0-t1-t2-c2-c1-c0 (nearest-neighbor pulses only) in 28 pulses.

blueqat.eo.sequences.rz_sequence(phase, offset=0)[source]

Logical RZ(phase): a single pulse on the (0,1) pair (the singlet in |0_L> picks up e^{i theta}, giving RZ(-theta) up to global phase).

Parameters:
Return type:

List[Tuple[Tuple[int, int], float]]

blueqat.eo.sequences.x_sequence(offset=0)[source]

Logical X in 3 pulses.

Parameters:

offset (int)

Return type:

List[Tuple[Tuple[int, int], float]]

blueqat.eo.sequences.h_sequence(offset=0)[source]

Logical Hadamard in 3 pulses.

Parameters:

offset (int)

Return type:

List[Tuple[Tuple[int, int], float]]

blueqat.eo.sequences.y_sequence(offset=0)[source]

Logical Y = X after Z (equal to iY, a global phase).

Parameters:

offset (int)

Return type:

List[Tuple[Tuple[int, int], float]]

blueqat.eo.sequences.rx_sequence(phase, offset=0)[source]

Logical RX(phase) = H RZ(phase) H.

Parameters:
Return type:

List[Tuple[Tuple[int, int], float]]

blueqat.eo.sequences.ry_sequence(phase, offset=0)[source]

Logical RY(phase) = S RX(phase) S^dagger (applied right-to-left).

Parameters:
Return type:

List[Tuple[Tuple[int, int], float]]

blueqat.eo.sequences.cx_sequence(control_offset, target_offset)[source]

Serial Fong-Wandzura CNOT: 28 exchange pulses on the linear chain t0-t1-t2-c2-c1-c0 (control spins c*, target spins t*), exact up to a global phase and independent of both qubits’ gauge states.

Parameters:
  • control_offset (int)

  • target_offset (int)

Return type:

List[Tuple[Tuple[int, int], float]]

blueqat.eo.sequences.cz_sequence(control_offset, target_offset)[source]

Encoded CZ = (I x H) CX (I x H) on the target logical qubit.

Parameters:
  • control_offset (int)

  • target_offset (int)

Return type:

List[Tuple[Tuple[int, int], float]]

blueqat.eo.sequences.swap_sequence(offset_a, offset_b)[source]

Encoded SWAP: swap the two triples spin-by-spin (3 full-SWAP pulses).

Parameters:
  • offset_a (int)

  • offset_b (int)

Return type:

List[Tuple[Tuple[int, int], float]]

blueqat.eo.sequences.sequence_to_circuit(sequence, n_physical_qubits)[source]

Build an exchange-pulse Circuit from a sequence of ((i, j), theta).

Parameters:
Return type:

Circuit

Differentiable synthesis of logical EO gates as short exchange-pulse sequences, using PyTorch autograd (the whole pipeline – pulse areas -> exchange matrices -> logical block -> fidelity – is differentiable).

This is what allows going beyond the fixed analytic gate tables: any target SU(2) can be compiled into a few constant-amplitude pulses.

blueqat.eo.optimizer.synthesize_1q(target, n_pulses=4, n_restarts=8, max_iter=400, fidelity_goal=0.999999999, seed=0, offset=0)[source]

Synthesize a logical 1-qubit gate as n_pulses exchange pulses alternating on pairs (0,1) and (1,2) of one triple.

Returns the pulse sequence in application order (compatible with sequences.sequence_to_circuit). Raises RuntimeError if no restart reaches fidelity_goal – some targets need more pulses (4 suffices for generic SU(2) with these two 120-degree-tilted rotation axes).

Parameters:
  • target (Tensor)

  • n_pulses (int)

  • n_restarts (int)

  • max_iter (int)

  • fidelity_goal (float)

  • seed (int | None)

  • offset (int)

Return type:

List[Tuple[Tuple[int, int], float]]

blueqat.eo.optimizer.synthesize_2q(target, pairs, initial_thetas=None, n_restarts=4, max_iter=1000, fidelity_goal=0.99999999, seed=0)[source]

Synthesize an encoded 2-logical-qubit gate (logical qubit 0 on spins 0-2, logical qubit 1 on spins 3-5) as exchange pulses on the given pair pattern.

The loss demands a gauge-independent, gauge-preserving implementation: the logical block must equal target with one common phase in all four total-Sz sectors (leakage automatically suppresses the fidelity, so it needs no separate penalty). Note that some natural constructions are gauge-permuting instead – e.g. the 3-pulse physical triple swap realizes an encoded SWAP but exchanges the two gauge states with it – and such gates cannot (and need not) be found by this loss.

Pass initial_thetas to refine a known sequence – e.g. to re-calibrate the Fong-Wandzura angles after hardware perturbations – instead of starting from random pulses; from-scratch synthesis of long 2-qubit sequences is a hard non-convex problem and may need many restarts.

Parameters:
Return type:

List[Tuple[Tuple[int, int], float]]

blueqat.eo.optimizer.quantize_sequence(sequence, step)[source]

Snap every pulse area to the nearest multiple of step and drop pulses that round to zero – the operational constraint of constant- amplitude hardware whose pulse durations come in discrete clock ticks.

Check the result’s fidelity yourself (e.g. via encoding.logical_action); a coarse step degrades the gate.

Parameters:
Return type:

List[Tuple[Tuple[int, int], float]]

blueqat.eo.optimizer.THREE_PULSE_REACH = 0.8660254037844386

The two exchange pairs of a triple act on the logical qubit as rotations about axes 120 degrees apart – pair (0,1) about -z, pair (1,2) about (sqrt(3)/2, 0, 1/2) – and by exactly the pulse area, measured. That fixes what three pulses can reach: the off-diagonal entry of a product Ra Rb Ra has modulus (sqrt(3)/2) |sin(beta/2)|, and the outer two pulses are diagonal, so they cannot change it.

blueqat.eo.optimizer.decompose_1q(target, offset=0, samples=720)[source]

A logical 1-qubit gate as three or four exchange pulses, in closed form.

Exact, and far shorter than composing the analytic tables: measured against them, rx goes from seven pulses to three or four and ry from nine. On exchange-only hardware a pulse is a gate, so that is the error budget.

Three suffice when |target[0,1]| <= sqrt(3)/2, which for rx(theta) means theta <= 2*pi/3. Beyond it a fourth pulse is applied first to bring the target inside: measured over random unitaries outside the reach, the largest residual after the best fourth pulse is 0.829 against the 0.866 bound, so four always suffice. samples is how finely that fourth angle is searched before being refined; it is a one-dimensional minimum, not a fit over the whole sequence.

Parameters:
  • target (Tensor)

  • offset (int)

  • samples (int)

Return type:

List[Tuple[Tuple[int, int], float]]

Pulse schedules: the hardware-facing time-resolved view of an exchange circuit.

to_schedule turns a sequence of exchange pulses (or a Circuit of exch gates) into a JSON-compatible dict with explicit start times, packing pulses on disjoint spin pairs in parallel (ASAP scheduling; pulses on disjoint pairs commute, so this never changes the unitary). The format is designed to be handed to pulse-level control stacks (e.g. spinQICK-style backends) or submitted through blueqat.cloud.

Schema:

{
  "format": "blueqat-eo-schedule",
  "version": "1",
  "n_spins": 6,
  "amplitude": 1.0,          # exchange integral J during a pulse
  "pulses": [
    {"start": 0.0, "duration": 3.14159, "pair": [0, 1], "theta": 3.14159},
    ...
  ],
  "total_duration": 12.56637
}

Durations are theta / amplitude (constant-amplitude pulses: the pulse area theta = J * t is what fixes the gate).

blueqat.eo.schedule.to_schedule(source, amplitude=1.0, n_spins=0)[source]

Build a time-resolved pulse schedule with ASAP parallel packing.

Each pulse starts as soon as both of its spins are free; pulses touching disjoint pairs run simultaneously. Relative order of pulses sharing a spin is preserved, so the scheduled unitary equals the sequential one.

The exchange unitary is exactly 2*pi-periodic in the pulse area, so theta is canonicalized into [0, 2*pi) – a negative area (e.g. from a daggered circuit) becomes the equivalent positive-duration pulse, and pulses whose area is a multiple of 2*pi (no-ops) are dropped.

Parameters:
Return type:

Dict[str, Any]

blueqat.eo.schedule.from_schedule(schedule)[source]

Rebuild an exchange-pulse Circuit from a schedule dict.

Pulses are replayed in order of start time (ties broken by list order). That reproduces the original unitary exactly because overlapping pulses only ever act on disjoint pairs, which is what to_schedule guarantees. A hand-written schedule need not, so it is checked here rather than serialized into a different unitary without comment.

Parameters:

schedule (Dict[str, Any])

Return type:

Circuit

blueqat.eo.schedule.schedule_stats(schedule)[source]

Summary numbers: pulse count, serial vs scheduled duration, speedup.

Parameters:

schedule (Dict[str, Any])

Return type:

Dict[str, float]

The ‘eo’ backend: transpile a logical Circuit into exchange pulses.

import blueqat.eo # registers the backend physical = Circuit(2).h[0].cx[0, 1].run(backend=’eo’)

Logical qubit i is encoded in physical spins 3i, 3i+1, 3i+2, and the output is an ordinary Circuit containing only exch pulses, runnable on any simulation backend. All logical gates are exact up to global phase.

Topology note: the emitted pulses assume any pair inside the two triples involved in a gate can be pulsed (in particular, the Fong-Wandzura CNOT’s bridge pulse connects spin 3c+2 with spin 3t+2, and the encoded SWAP pulses pair the triples spin-by-spin). This is always fine for simulation; mapping onto strict nearest-neighbor-only hardware additionally requires dot orientation assignment and spin-level SWAP routing, which is future work (cf. exchange-pulse-optimizer).

class blueqat.eo.transpiler.EOTranspiler[source]

Transpiler backend converting logical circuits to exchange pulses.

run(gates, n_qubits, *args, **kwargs)[source]

shortest=True solves each single-qubit gate in closed form rather than reading it out of the analytic tables.

The tables compose known sequences, which is correct and longer than necessary: measured, an rx costs seven pulses there and three or four solved directly, an ry nine. A pulse is a gate on this hardware, so that is the error budget. It is off by default because it changes the emitted pulses for circuits that already work, and a device schedule is not something to alter without being asked.

Parameters:
Return type:

Circuit

Cloud

API-key based access to the Blueqat cloud service (https://qapi.blueqat.app).

Credential resolution order:

  1. An explicit configure(api_key=…) call in the current process.

  2. The BLUEQAT_API_KEY environment variable.

  3. The config file ~/.blueqat/config.json (written by save_api_key, created with owner-only permissions).

Importing this module registers the cloud backend, so a circuit can be submitted with the same API as local simulation:

import blueqat.cloud
Circuit(2).h[0].cx[0, 1].m[:].run(backend='cloud', shots=100)   # Counter
Circuit(2).h[0].cx[0, 1].run(backend='cloud')                   # statevector
Circuit(2).h[0].run(backend='cloud', hamiltonian=1.0 * Z[0])    # <psi|H|psi>

Results follow the SDK’s conventions (Counter keys are q_{n-1}…q0 etc.), so switching between local and cloud backends needs no code changes. Module helpers cover the rest of the REST API: health, me, circuit_info, vqe_run, qaoa_run, hardware_status, hardware_qpus, submit_hardware_job (which requires confirm=True – real hardware, real cost).

Get an API key at https://mcp.blueqat.app/login.

blueqat.cloud.GATEWAY_TIMEOUTS = frozenset({504, 522, 523, 524})

Status codes meaning “the gateway gave up waiting”, not “the work failed”. Cloudflare’s 524 in particular fires after 100 seconds of silence from the origin – a limit on how long a reply may take to start, not on how long the work may take. Treating one as a failure invites a resubmission, which for a hardware job costs another slot and more money.

exception blueqat.cloud.CloudOutcomeUnknown[source]

The request’s fate is unknown: it may have succeeded.

Raised instead of a plain error when the connection or the gateway timed out, so that a caller can tell “this did not happen” apart from “I do not know whether this happened” – and does not retry the second one blindly.

blueqat.cloud.config_path()[source]

Path of the persistent config file (override dir with BLUEQAT_CONFIG_DIR).

Return type:

Path

blueqat.cloud.save_api_key(api_key, endpoint=None)[source]

Persist the API key to the config file with owner-only permissions.

Parameters:
  • api_key (str)

  • endpoint (str | None)

Return type:

Path

blueqat.cloud.delete_api_key()[source]

Remove the stored API key from the config file (if present).

Return type:

None

blueqat.cloud.get_api_key()[source]

Resolve the API key: configure() > environment > config file.

Return type:

str | None

blueqat.cloud.get_endpoint()[source]

Resolve the service endpoint: configure() > config file > default.

Return type:

str

blueqat.cloud.configure(api_key=None, endpoint=None, transport=None)[source]

Set session-level cloud settings (highest priority, not persisted).

transport is a callable (method, path, payload, api_key, endpoint) returning the decoded JSON response; inject one for tests.

Parameters:
Return type:

None

blueqat.cloud.reset_configuration()[source]

Clear session-level settings set by configure (env/file are untouched).

Return type:

None

blueqat.cloud.circuit_to_gates(circuit)[source]

Convert a Circuit into the API’s gate-list format: [{"gate": "h", "qubits": [0]}, {"gate": "rx", "qubits": [0], "params": [0.5]}, ...] (slices and named blocks are expanded).

Return type:

Tuple[int, List[dict]]

blueqat.cloud.hamiltonian_to_terms(hamiltonian)[source]

Convert a Pauli Expr/Term into the API’s term list [{"coeff": c, "paulis": [{"op": "X", "qubit": 0}, ...]}, ...].

Identity (constant) terms can’t be sent over the wire; they are returned separately as a float to add to the expectation value locally.

Return type:

Tuple[List[dict], float]

class blueqat.cloud.CloudBackend[source]

Backend submitting circuits to https://qapi.blueqat.app (POST /v1/circuits/run). Results are converted back to SDK conventions, so it is a drop-in replacement for the local backends.

run(gates, n_qubits, *args, **kwargs)[source]

Execute the quantum circuit represented by a list of gates.

Parameters:
Return type:

Any

blueqat.cloud.health()[source]

Service health (no authentication required).

Return type:

dict

blueqat.cloud.me()[source]

The authenticated account: tier, limits and remaining quota.

Return type:

dict

blueqat.cloud.circuit_info(circuit)[source]

Server-side circuit validation and stats without running it.

Return type:

dict

blueqat.cloud.vqe_run(hamiltonian, n_qubits, layers=1)[source]

Run VQE on the cloud for a Pauli Hamiltonian.

Parameters:
Return type:

dict

blueqat.cloud.qaoa_run(qubo, steps=1, shots=256)[source]

Run QAOA on the cloud for a QUBO given as [{"i": 0, "j": 1, "value": 2.0}, ...] (see the API docs).

Parameters:
Return type:

dict

blueqat.cloud.hardware_status()[source]

Near-real-time hardware status snapshot.

Return type:

dict

blueqat.cloud.hardware_qpus()[source]

List available QPUs (authenticated).

Return type:

dict

blueqat.cloud.submit_hardware_job(circuit, shots, qpu_id=None, confirm=False, preserve_layout=False)[source]

Submit a circuit to real quantum hardware.

Requires confirm=True: hardware runs cost real money and are subject to your account’s quota.

Parameters:
  • shots (int)

  • qpu_id (str | None)

  • confirm (bool)

  • preserve_layout (bool)

Return type:

dict

blueqat.cloud.hardware_jobs(limit=20)[source]

List your recent hardware jobs, newest first.

This is the way to answer “did my submission actually land?” after a CloudOutcomeUnknown – check here before resubmitting, since a duplicate hardware job spends another slot and more money.

Parameters:

limit (int)

Return type:

dict

blueqat.cloud.hardware_job(task_id, qpu_id=None)[source]

Status of one hardware job.

Parameters:
  • task_id (str)

  • qpu_id (str | None)

Return type:

dict

blueqat.cloud.hardware_job_result(task_id, qpu_id=None)[source]

Result of a finished hardware job.

Parameters:
  • task_id (str)

  • qpu_id (str | None)

Return type:

dict

blueqat.cloud.cancel_hardware_job(task_id, qpu_id=None)[source]

Cancel a queued hardware job.

Parameters:
  • task_id (str)

  • qpu_id (str | None)

Return type:

dict

blueqat.cloud.hardware_quote(shots, payer)[source]

What a hardware run would cost, before committing to it.

Parameters:
Return type:

dict

blueqat.cloud.hardware_next_window(qpu_id=None)[source]

When the next hardware submission window opens.

Hardware is not always accepting jobs; a submission outside a window queues until the next one.

Parameters:

qpu_id (str | None)

Return type:

dict

blueqat.cloud.hardware_calibration(qpu_id=None)[source]

Current per-qubit calibration data (error rates, coherence times).

Parameters:

qpu_id (str | None)

Return type:

dict

MCP server

MCP (Model Context Protocol) server exposing blueqat to LLM clients.

Install the optional dependency and register the server with an MCP client (Claude Desktop, Claude Code, …):

pip install blueqat[mcp]

// e.g. Claude Desktop’s config: { “mcpServers”: { “blueqat”: { “command”: “blueqat-mcp” } } }

Circuits are exchanged as OpenQASM 2.0 text (parsed with blueqat’s eval-free parser) and Hamiltonians as Pauli-expression strings parsed by blueqat.utils.parse_hamiltonian() – no code execution ever happens on tool inputs.

The tool implementations below are plain functions returning JSON-compatible dicts (so they are unit-testable without an MCP client); build_server() wraps them into a FastMCP server and main() serves it over stdio.

blueqat.mcp_server.run_circuit(qasm, shots=None, backend='tensornet')[source]

Run an OpenQASM 2.0 circuit and return the result.

With shots, returns measurement counts. Without, returns the full statevector for small circuits, or the largest basis-state probabilities for wide ones.

Parameters:
  • qasm (str)

  • shots (int | None)

  • backend (str)

Return type:

Dict[str, Any]

blueqat.mcp_server.circuit_stats(qasm)[source]

Qubit count, depth and gate counts of an OpenQASM 2.0 circuit.

Parameters:

qasm (str)

Return type:

Dict[str, Any]

blueqat.mcp_server.expectation_value(qasm, hamiltonian)[source]

<psi|H|psi> for the circuit’s final state.

hamiltonian is a Pauli expression like “1.5*Z[0]*Z[1] - 0.5*X[0] + 2” (indices as [n] or directly after the letter; * is optional).

Parameters:
  • qasm (str)

  • hamiltonian (str)

Return type:

Dict[str, Any]

blueqat.mcp_server.draw_circuit_png(qasm)[source]

Render the circuit diagram and return PNG bytes.

Parameters:

qasm (str)

Return type:

bytes

blueqat.mcp_server.eo_transpile(qasm)[source]

Transpile a logical circuit to exchange-only spin-qubit pulses (3 physical spins per logical qubit) and summarize the pulse schedule.

Parameters:

qasm (str)

Return type:

Dict[str, Any]

blueqat.mcp_server.blueqat_info()[source]

Version and capability summary of this blueqat installation.

Return type:

Dict[str, Any]

blueqat.mcp_server.build_server()[source]

Create the MCP server (requires the optional mcp dependency).

Supports both the mcp 2.x high-level API (MCPServer) and the 1.x one (FastMCP) – they share the tool()/run() surface used here.

blueqat.mcp_server.main()[source]

Entry point for the blueqat-mcp console script (stdio transport).

Return type:

None

Circuit utilities

Parser for a practical subset of OpenQASM 2.0 (the qelib1.inc gate set) into a Circuit.

This is the reverse of Circuit.to_qasm().

blueqat.circuit_funcs.qasm_parser.MAX_EXPONENT = 64

Largest exponent an angle expression may use. ** is unbounded arithmetic: 9**9**9 has no answer a machine will finish computing, and this parser reads text arriving from MCP clients, so an angle is not a place to allow that.

blueqat.circuit_funcs.qasm_parser.look_alike_characters(text)[source]

Characters that are not what they look like, and what they should be.

Text pasted out of a PDF or a word processor carries characters that render identically to ASCII or to an ordinary ideograph but are different code points – full-width punctuation and digits, and the 214 Kangxi radicals, where 子 (U+5B50) and ⼦ (U+2F26) are indistinguishable on screen. A program carrying them fails to parse for a reason nobody can see by looking.

Returns {character: what it normalizes to} for each distinct character NFKC would change.

⚠ That is a wide net, and using it as a “this text is damaged” test gives false positives on perfectly good Japanese. Full-width brackets and colons are correct typography; NFKC also turns ① into 1, ㎡ into m2, Ⅳ into IV and … into ..., none of which is a repair. Use always_wrong_characters to ask whether something is broken; use this one to describe what is there.

Parameters:

text (str)

Return type:

Dict[str, str]

blueqat.circuit_funcs.qasm_parser.EXTRACTION_DAMAGE_RANGES = ((12032, 12245),)

The one range whose members can be called damage on sight. Their Unicode names say what they are – KANGXI RADICAL CHILD, KANGXI RADICAL TALL – so a character from a radical table appearing in running prose is not something anyone chose. All 214 normalize onto an ordinary ideograph.

⚠ Even here, “safe to repair in stored text” depends on where the text came from. Extracted from a PDF, one of these is an accident. Typed by a person or produced by a model, it is what they entered, and rewriting it is rewriting them. The character alone does not settle it.

blueqat.circuit_funcs.qasm_parser.PRESENTATION_RANGES = ((63744, 64255), (65296, 65305), (65313, 65338), (65345, 65370), (65377, 65439))

Look-alikes that may be exactly what someone meant. Normalize these into a search index, never in the stored text.

The compatibility ideographs are the trap. Their names say nothing – CJK COMPATIBILITY IDEOGRAPH-FA10 – and they normalize onto 塚, 晴 and 祥, which is to say onto characters that appear in people’s names. A document carrying one may be spelling somebody’s name correctly, and repairing the stored text would spell it wrong.

Full-width letters are the registered form of some company names and appear in quotations that must not be altered; half-width kana is a presentation choice. The three full-width intervals are listed separately on purpose: FF10-FF5A as one span would swallow the full-width colon, question mark and brackets, which are ordinary Japanese punctuation.

blueqat.circuit_funcs.qasm_parser.LOOK_ALIKE_RANGES = ((12032, 12245), (63744, 64255), (65296, 65305), (65313, 65338), (65345, 65370), (65377, 65439))

QASM is ASCII by definition, so the question of whether a character was intended does not arise inside one.

Type:

Both, which is what a program cares about

blueqat.circuit_funcs.qasm_parser.extraction_damage(text)[source]

Kangxi radicals, which say in their own names that they are misplaced.

U+2F26 renders exactly like U+5B50 and is a different character, so a document carrying it cannot be searched for its own words.

⚠ Whether repairing the stored text is right still depends on where the text came from: extracted from a document, one of these is an accident; typed by a person or emitted by a model, it is their input. Normalizing a search index is always safe and achieves the searching either way.

Parameters:

text (str)

Return type:

Dict[str, str]

blueqat.circuit_funcs.qasm_parser.presentation_variants(text)[source]

Look-alikes that may be deliberate. Normalize an index, not the text.

Compatibility ideographs normalize onto characters that appear in people’s names – U+FA10, U+FA12 and U+FA1A onto 塚, 晴 and 祥 – so a document carrying one may be spelling a name correctly. Full-width letters are the registered form of some company names and appear inside quotations. Nothing here can tell an intentional one from an accident, so rewriting the stored text changes names and misquotes sources. Normalize both the index and the query instead, and leave the text as it was written.

Parameters:

text (str)

Return type:

Dict[str, str]

blueqat.circuit_funcs.qasm_parser.always_wrong_characters(text)[source]

Every look-alike, damage or presentation, with its repair.

The union of extraction_damage and presentation_variants. Right for a program – QASM is ASCII, so anything here is a mistake in one – and the wrong question for prose, where the two halves want opposite treatment.

Only characters NFKC actually changes are returned. Reporting one whose normalized form is itself would be naming a problem and offering the problem as its own solution; see unfixable_lookalikes.

Parameters:

text (str)

Return type:

Dict[str, str]

blueqat.circuit_funcs.qasm_parser.unfixable_lookalikes(text)[source]

Look-alikes that normalizing will not resolve.

Twelve compatibility ideographs – U+FA0E, FA0F, FA11, FA13, FA14, FA1F, FA21, FA23, FA24, FA27, FA28 and FA29 – normalize to themselves, so U+FA11 and U+5D0E stay different after NFKC on both sides. Variant forms of a personal name are the usual way to meet them, and they need a different answer entirely.

⚠ These are not the whole of the problem, only the part that is in range. Ordinary variant ideographs – U+9AD9 against U+9AD8, say – are not compatibility characters at all and no normalization touches them. Matching people by name does not close either way; matching them by identifier does.

Returned as {character: itself} so that “found it” and “fixed it” stay distinguishable: calling a normalization pass a resolution here is how the same report comes back a second time.

Parameters:

text (str)

Return type:

Dict[str, str]

blueqat.circuit_funcs.qasm_parser.from_qasm(qasm, normalize=False)[source]

Parse an OpenQASM 2.0 program (the qelib1.inc gate set) into a Circuit.

normalize applies NFKC first, folding full-width punctuation and Kangxi radicals onto their ASCII and ideographic equivalents. It is off by default because silently rewriting input is a guess at what was meant; when parsing fails, the error says whether such characters are present, which is something no amount of looking at the text will reveal.

Parameters:
Return type:

Circuit

Defines JSON serializer and deserializer for Blueqat circuits.

blueqat.circuit_funcs.json_serializer.serialize(c)[source]

Serialize Circuit into JSON-compatible dictionary.

In this implementation, the serialized circuit is automatically flattened to break down multi-target operations into atomic gates.

Parameters:

c (Circuit)

Return type:

CircuitJsonDictV2

blueqat.circuit_funcs.json_serializer.deserialize(data)[source]

Deserialize JSON-compatible dictionary back into a Circuit object.

Parameters:

data (CircuitJsonDictV1 | CircuitJsonDictV2)

Return type:

Circuit

This module provides a feature to convert a quantum circuit to a unitary matrix.

blueqat.circuit_funcs.circuit_to_unitary.circuit_to_unitary(circ, *runargs, **runkwargs)[source]

Convert a quantum circuit into its corresponding unitary matrix representation.

This function simulates the circuit for all computational basis states to construct the full unitary matrix.

Parameters:
  • circ (Circuit) – The quantum circuit to be converted.

  • *runargs – Positional arguments passed to circuit execution backend.

  • **runkwargs – Keyword arguments passed to circuit execution backend.

Returns:

The unitary matrix representing the total circuit operation.

Return type:

np.ndarray

This module provides a feature to flatten circuit operations by expanding multi-targets.

blueqat.circuit_funcs.flatten.flatten(c)[source]

Expands slice and multiple targets into single target operations.

This function normalizes the circuit so that each gate or measurement operation applies to explicit, un-sliced single qubits (or single pairs for two-qubit gates).

Parameters:

c (Circuit) – The quantum circuit to flatten.

Returns:

A new flattened Circuit object.

Return type:

Circuit

Raises:

ValueError – If an unexpected or unprocessable operation type is encountered.