Abstract Registers

Quantum circuits process quantum states. A quantum state being processing by a quantum circuit will be stored on a quantum register. In Yao we provide several types for registers. The default type for registers is the ArrayReg which is defined in YaoArrayRegister.jl.

The registers can be extended by subtyping AbstractRegister and define correspinding register interfaces defined in YaoBase.jl, which includes:

Minimal Required Interfaces

The following interfaces are the minial required interfaces to make a register's printing work and be able to accept certain gates/blocks.

But if you don't want to work with our default printing, you could define your custom printing with Base.show.

nactive(register) -> Int

Returns the number of active qubits.


Operators always apply on active qubits.


you can define instruct!, to provide specialized instructions for the registers from plain storage types.

Qubit Management Interfaces

addbits!(register, n::Int) -> register
addbits!(n::Int) -> λ(register)

Add n qubits to given register in state |0>. i.e. |psi> -> |000> ⊗ |psi>, increased bits have higher indices.

If only an integer is provided, then returns a lambda function.

reorder!(reigster, orders)

Reorder the locations of register by input orders.


Qubit Scope Management Interfaces

LDT format

Concepturely, a wave function $|\psi\rangle$ can be represented in a low dimentional tensor (LDT) format of order-3, L(f, r, b).

  • f: focused (i.e. operational) dimensions
  • r: remaining dimensions
  • b: batch dimension.

For simplicity, let's ignore batch dimension for the now, we have

\[|\psi\rangle = \sum\limits_{x,y} L(x, y, .) |j\rangle|i\rangle\]

Given a configuration x (in operational space), we want get the i-th bit using (x<<i) & 0x1, which means putting the small end the qubit with smaller index. In this representation L(x) will get return $\langle x|\psi\rangle$.


Why not the other convension: Using the convention of putting 1st bit on the big end will need to know the total number of qubits n in order to know such positional information.

HDT format

Julia storage is column major, if we reshape the wave function to a shape of $2\times2\times ... \times2$ and get the HDT (high dimensional tensor) format representation H, we can use H($x_1, x_2, ..., x_3$) to get $\langle x|\psi\rangle$.

focus!(register, locs) -> register

Focus the wires on specified location.


julia> focus!(r, (1, 2, 4))
focus!(locs...) -> f(register) -> register

Lazy version of focus!, this returns a lambda which requires a register.

focus(f, register, locs...)

Call a callable f under the context of focus. See also focus!.


print the focused register

julia> r = ArrayReg(bit"101100")
    active qubits: 6/6

julia> focus(x->(println(x);x), r, 1, 2);
    active qubits: 2/6
relax!(register[, locs]; to_nactive=nqubits(register)) -> register

Inverse transformation of focus!, where to_nactive is the number of active bits for target register.

relax!(locs::Int...; to_nactive=nqubits(register)) -> f(register) -> register

Lazy version of relax!, it will be evaluated once you feed a register to its output lambda.

Measurement Interfaces

measure(register[, operator][, locs]; nshots=1, rng=Random.GLOBAL_RNG) -> Vector{Int}

Return measurement results of qubits in locs. If locs is not provided, all current active qubits are measured (regarding to active qubits, see focus! and relax!).

measure!([postprocess,] [operator, ]register[, locs]; rng=Random.GLOBAL_RNG)

Measure current active qubits or qubits at locs. After measure and collapse,

* do nothing if postprocess is `NoPostProcess`
* reset to result state to `postprocess.config` if `postprocess` is `ResetTo`.
* remove the qubit if `postprocess` is `RemoveMeasured`
Missing docstring.

Missing docstring for YaoBase.measure_remove!. Check Documenter's build log for details.

Missing docstring.

Missing docstring for YaoBase.measure_collapseto!. Check Documenter's build log for details.

select!(dest::AbstractRegister, src::AbstractRegister, bits::Integer...) -> AbstractRegister
select!(register::AbstractRegister, bits::Integer...) -> register

select a subspace of given quantum state based on input eigen state bits. See also select.


select!(reg, 0b110) will select the subspace with (focused) configuration 110. After selection, the focused qubit space is 0, so you may want call relax! manually.


Developers should overload select!(r::RegisterType, bits::NTuple{N, <:Integer}) and do not assume bits has specific number of bits (e.g Int64), or it will restrict the its maximum available number of qubits.

select!(b::Integer) -> f(register)

Lazy version of select!. See also select.


fidelity(register1, register2)

Return the fidelity between two states.


The fidelity of two quantum state for qubits is defined as:

\[F(ρ, σ) = tr(\sqrt{\sqrt{ρ}σ\sqrt{ρ}})\]

Or its equivalent form (which we use in numerical calculation):

\[F(ρ, σ) = sqrt(tr(ρσ) + 2 \sqrt{det(ρ)det(σ)})\]


  • Jozsa R. Fidelity for mixed quantum states[J]. Journal of modern optics, 1994, 41(12): 2315-2323.
  • Nielsen M A, Chuang I. Quantum computation and quantum information[J]. 2002.

The original definition of fidelity $F$ was from "transition probability", defined by Jozsa in 1994, it is the square of what we use here.

fidelity(r1::ArrayReg, r2::ArrayReg)

Calcuate the fidelity between r1 and r2, if r1 or r2 is not pure state (nactive(r) != nqubits(r)), the fidelity is calcuated by purification. See also pure_state_fidelity, purification_fidelity.

tracedist(register1, register2)

Return the trace distance of register1 and register2.


Trace distance is defined as following:

\[\frac{1}{2} || A - B ||_{tr}\]


  • https://en.wikipedia.org/wiki/Trace_distance
viewbatch(register, i::Int) -> AbstractRegister{1}

Returns a view of the i-th slice on batch dimension.