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 Yao.Registers.DefaultRegister
.
You can directly use factory method register
Storage
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 momentum, 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$.
Operations
Kronecker product of operators
In order to put small bits on little end, the Kronecker product is $O = o_n \otimes \ldots \otimes o_2 \otimes o_1$ where the subscripts are qubit indices.
Measurements
Measure means sample
and projection
.
Sample
Suppose we want to measure operational subspace, we can first get
Then we sample an $a\sim p(x)$. If we just sample and don't really measure (change wave function), its over.
Projection
Good! then we can just remove the operational qubit space since x
and y
spaces are totally decoupled and x
is known as in state a
, then we get
where l = L(a:a, :, :)/sqrt(p(a))
.
Registers
Yao.Registers.AbstractRegister
— Type.AbstractRegister{B, T}
abstract type that registers will subtype from. B
is the batch size, T
is the data type.
Required Properties
Property | Description | default |
---|---|---|
viewbatch(reg,i) | get the view of slice in batch dimension. | |
nqubits(reg) | get the total number of qubits. | |
nactive(reg) | get the number of active qubits. | |
state(reg) | get the state of this register. It always return the matrix stored inside. | |
(optional) | ||
nremain(reg) | get the number of remained qubits. | nqubits - nactive |
datatype(reg) | get the element type Julia should use to represent amplitude) | T |
nbatch(reg) | get the number of batch. | B |
length(reg) | alias of nbatch , for interfacing. | B |
Required Methods
Multiply
*(op, reg)
define how operator op
act on this register. This is quite useful when there is a special approach to apply an operator on this register. (e.g a register with no batch, or a register with a MPS state, etc.)
be careful, generally, operators can only be applied to a register, thus we should only overload this operation and do not overload *(reg, op)
.
Pack Address
pack addrs
together to the first k-dimensions.
Example
Given a register with dimension [2, 3, 1, 5, 4]
, we pack [5, 4]
to the first 2 dimensions. We will get [5, 4, 2, 3, 1]
.
Focus Address
focus!(reg, range)
merge address in range
together as one dimension (the active space).
Example
Given a register with dimension (2^4)x3
and address [1, 2, 3, 4], we focus address [3, 4]
, will pack [3, 4]
together and merge them as the active space. Then we will have a register with size 2^2x(2^2x3)
, and address [3, 4, 1, 2]
.
Initializers
Initializers are functions that provide specific quantum states, e.g zero states, random states, GHZ states and etc.
register(::Type{RT}, raw, nbatch)
an general initializer for input raw state array.
register(::Val{InitMethod}, ::Type{RT}, ::Type{T}, n, nbatch)
init register type RT
with InitMethod
type (e.g Val{:zero}
) with element type T
and total number qubits n
with nbatch
. This will be auto-binded to some shortcuts like zero_state
, rand_state
.
Yao.Registers.DefaultRegister
— Type.DefaultRegister{B, T} <: AbstractRegister{B, T}
Default type for a quantum register. It contains a dense array that represents a batched quantum state with batch size B
of type T
.
Yao.Registers.DensityMatrix
— Type.DensityMatrix{B, T, MT<:AbstractArray{T, 3}}
DensityMatrix(state) -> DensityMatrix
Density Matrix.
Yao.Registers.@bit_str
— Macro.@bit_str -> BitStr
Construct a bit string. such as bit"0000"
. The bit strings also supports string concat. Just use it like normal strings.
LinearAlgebra.normalize!
— Function.normalize!(r::AbstractRegister) -> AbstractRegister
Return the register with normalized state.
Yao.Intrinsics.hypercubic
— Method.hypercubic(r::DefaultRegister) -> AbstractArray
Return the hypercubic form (high dimensional tensor) of this register, only active qubits are considered.
Yao.Registers.addbit!
— Function.addbit!(r::AbstractRegister, n::Int) -> AbstractRegister
addbit!(n::Int) -> Function
addbit the register by n bits in state |0>. i.e. |psi> -> |000> ⊗ |psi>, addbit bits have higher indices. If only an integer is provided, then perform lazy evaluation.
Yao.Registers.density_matrix
— Function.density_matrix(register)
Returns the density matrix of this register.
Yao.Registers.fidelity
— Function.fidelity(reg1::AbstractRegister, reg2::AbstractRegister) -> Vector
Return the fidelity between two states.
Yao.Registers.focus!
— Function.focus!(reg::DefaultRegister, bits::Ints) -> DefaultRegister
focus!(locs::Int...) -> Function
Focus register on specified active bits.
Yao.Registers.focus!
— Method.focus!(func, reg::DefaultRegister, locs) -> DefaultRegister
Yao.Registers.invorder!
— Function.invorder!(reg::AbstractRegister) -> AbstractRegister
Inverse the order of lines inplace.
Yao.Registers.isnormalized
— Function.isnormalized(reg::AbstractRegister) -> Bool
Return true if a register is normalized else false.
Yao.Registers.measure!
— Method.measure!(reg::AbstractRegister; [locs]) -> Int
measure and collapse to result state.
Yao.Registers.measure
— Method.measure(register, [locs]; [nshot=1]) -> Vector
measure active qubits for nshot
times.
Yao.Registers.measure_remove!
— Method.measure_remove!(register; [locs]) -> Int
measure the active qubits of this register and remove them.
Yao.Registers.measure_reset!
— Method.measure_and_reset!(reg::AbstractRegister; [locs], [val=0]) -> Int
measure and set the register to specific value.
Yao.Registers.oneto
— Method.oneto({reg::DefaultRegister}, n::Int=nqubits(reg)) -> DefaultRegister
Return a register with first 1:n bits activated, reg
here can be lazy.
Yao.Registers.probs
— Function.probs(r::AbstractRegister)
Returns the probability distribution in computation basis $|<x|ψ>|^2$.
Yao.Registers.probs
— Method.probs(dm::DensityMatrix{B, T}) where {B,T}
Return probability from density matrix.
Yao.Registers.product_state
— Method.product_state([::Type{T}], n::Int, config::Int, nbatch::Int=1) -> DefaultRegister
a product state on given configuration config
, e.g. product_state(ComplexF64, 5, 0) will give a zero state on a 5 qubit register.
Yao.Registers.rand_state
— Method.rand_state([::Type{T}], n::Int, nbatch::Int=1) -> DefaultRegister
here, random complex numbers are generated using randn(ComplexF64)
.
Yao.Registers.rank3
— Method.rank3(reg::DefaultRegister) -> Array{T, 3}
Return the rank 3 tensor representation of state, the 3 dimensions are (activated space, remaining space, batch dimension).
Yao.Registers.register
— Function.register([type], bit_str, [nbatch=1]) -> DefaultRegister
Returns a DefaultRegister
by inputing a bit string, e.g
using Yao
register(bit"0000")
Yao.Registers.register
— Method.register(raw) -> DefaultRegister
Returns a DefaultRegister
from a raw dense array (Vector
or Matrix
).
Yao.Registers.relax!
— Function.relax!(reg::DefaultRegister; nbit::Int=nqubits(reg)) -> DefaultRegister
relax!(reg::DefaultRegister, bits::Ints; nbit::Int=nqubits(reg)) -> DefaultRegister
relax!(bits::Ints...; nbit::Int=-1) -> Function
Inverse transformation of focus, with nbit is the number of active bits of target register.
Yao.Registers.relaxedvec
— Method.relaxedvec(r::DefaultRegister) -> AbstractArray
Return a matrix (vector) for B>1 (B=1) as a vector representation of state, with all qubits activated.
Yao.Registers.reorder!
— Function.reorder!(reg::AbstractRegister, order) -> AbstractRegister
reorder!(orders::Int...) -> Function # currified
Reorder the lines of qubits, it also works for array.
Yao.Registers.reset!
— Function.reset!(reg::AbstractRegister, val::Integer=0) -> AbstractRegister
reset!
reg to default value.
Yao.Registers.select!
— Method.select!(reg::AbstractRegister, b::Integer) -> AbstractRegister
select!(b::Integer) -> Function
select specific component of qubit, the inplace version, the currified version will return a Function.
e.g. 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.
Yao.Registers.select
— Method.select(reg::AbstractRegister, b::Integer) -> AbstractRegister
the non-inplace version of select!
function.
Yao.Registers.state
— Function.state(reg) -> AbstractMatrix
get the state of this register. It always return the matrix stored inside.
Yao.Registers.statevec
— Method.statevec(r::DefaultRegister) -> AbstractArray
Return a state matrix/vector by droping the last dimension of size 1.
Yao.Registers.tracedist
— Function.tracedist(reg1::AbstractRegister, reg2::AbstractRegister) -> Vector
tracedist(reg1::DensityMatrix, reg2::DensityMatrix) -> Vector
trace distance.
Yao.Registers.tracedist
— Method.tracedist(dm1::DensityMatrix{B}, dm2::DensityMatrix{B}) -> Vector
Return trace distance between two density matrices.
Yao.Registers.uniform_state
— Method.uniform_state([::Type{T}], n::Int, nbatch::Int=1) -> DefaultRegister
uniform state, the state after applying H gates on |0> state.
Yao.Registers.viewbatch
— Function.viewbatch(r::AbstractRegister, i::Int) -> AbstractRegister{1}
Return a view of a slice from batch dimension.
Yao.Registers.zero_state
— Method.zero_state([::Type{T}], n::Int, nbatch::Int=1) -> DefaultRegister
Yao.Registers.ρ
— Function.ρ(register)
Returns the density matrix of this register.
Yao.nactive
— Function.nactive(x::AbstractRegister) -> Int
Return the number of active qubits.
note!!!
Operatiors always apply on active qubits.
Yao.Registers.BitStr
— Type.BitStr
String literal for qubits.
Base.join
— Function.join(reg1::AbstractRegister, reg2::AbstractRegister) -> Register
Merge two registers together with kronecker tensor product.
Base.repeat
— Function.repeat(reg::AbstractRegister{B}, n::Int) -> AbstractRegister
Repeat register in batch dimension for n
times.
Yao.Registers.shapeorder
— Method.Get the compact shape and order for permutedims.