# 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`

.

`YaoBase.nqubits`

— Function`nqubits(register) -> Int`

Returns the (total) number of qubits. See `nactive`

, `nremain`

for more details.

`YaoBase.nactive`

— Function`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

`YaoBase.addbits!`

— Function```
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.

`YaoBase.reorder!`

— 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

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$.

`YaoBase.focus!`

— Function`focus!(register, locs) -> register`

Focus the wires on specified location.

**Example**

```
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!`

.

**Example**

print the focused register

```
julia> r = ArrayReg(bit"101100")
ArrayReg{1,Complex{Float64},Array...}
active qubits: 6/6
julia> focus(x->(println(x);x), r, 1, 2);
ArrayReg{1,Complex{Float64},Array...}
active qubits: 2/6
```

`YaoBase.relax!`

— Function`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

`YaoBase.measure`

— Function`measure([, operator], register[, 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!`

).

`YaoBase.measure!`

— Function`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 for `YaoBase.measure_remove!`

. Check Documenter's build log for details.

Missing docstring for `YaoBase.measure_collapseto!`

. Check Documenter's build log for details.

`YaoBase.select!`

— Function```
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`

.

**Example**

`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.

## Others

`YaoBase.fidelity`

— Function`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`

.

`fidelity'(pair_or_reg1, pair_or_reg2) -> (g1, g2)`

Obtain the gradient with respect to registers and circuit parameters. For pair input `ψ=>circuit`

, the returned gradient is a pair of `gψ=>gparams`

, with `gψ`

the gradient of input state and `gparams`

the gradients of circuit parameters. For register input, the return value is a register.

`fidelity(register1, register2)`

Return the fidelity between two states.

**Definition**

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

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

**Reference**

- 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.

`YaoBase.tracedist`

— Function`tracedist(register1, register2)`

Return the trace distance of `register1`

and `register2`

.

**Definition**

Trace distance is defined as following:

**Reference**

- https://en.wikipedia.org/wiki/Trace_distance

`YaoBase.density_matrix`

— Function`density_matrix(register)`

Returns the density matrix of current active qubits.

`YaoBase.viewbatch`

— Function`viewbatch(register, i::Int) -> AbstractRegister{1}`

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