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 |
|---|---|---|
nqubits(reg) | get the total number of qubits. | |
nactive(reg) | get the number of active qubits. | |
nremain(reg) | get the number of remained qubits. | nqubits - nactive |
nbatch(reg) | get the number of batch. | B |
state(reg) | get the state of this register. It always return the matrix stored inside. | |
statevec(reg) | get the raveled state of this register. . | |
hypercubic(reg) | get the hypercubic form of this register. . | |
eltype(reg) | get the element type stored by this register on classical memory. (the type Julia should use to represent amplitude) | T |
copy(reg) | copy this register. | |
similar(reg) | construct a new register with similar configuration. |
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, randn_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.@bit_str — Macro.@bit_str -> QuBitStrConstruct a bit string. such as bit"0000". The bit strings also supports string concat. Just use it like normal strings.
Yao.Intrinsics.hypercubic — Function.hypercubic(r::AbstractRegister) -> AbstractArrayReturn the hypercubic form (high dimensional tensor) of this register, only active qubits are considered.
Yao.Registers.density_matrix — Function.density_matrix(register)Returns the density matrix of this register.
Yao.Registers.extend! — Method.extend!(r::DefaultRegister, n::Int) -> DefaultRegister
extend!(n::Int) -> Functionextend the register by n bits in state |0>. i.e. |psi> -> |000> ⊗ |psi>, extended bits have higher indices. If only an integer is provided, then perform lazy evaluation.
Yao.Registers.fidelity — Function.fidelity(reg1::DefaultRegister, reg2::DefaultRegister) -> VectorYao.Registers.focus! — Function.focus!(reg::DefaultRegister, bits::Ints) -> DefaultRegister
focus!(locs::Int...) -> FunctionFocus register on specified active bits.
Yao.Registers.focuspair! — Method.focuspair(locs::Int...) -> NTuple{2, Function}Return focus! and relax! function for specific lines.
Yao.Registers.isnormalized — Method.isnormalized(reg::DefaultRegister) -> BoolReturn true if a register is normalized else false.
Yao.Registers.measure — Function.measure(register, [n=1]) -> Vectormeasure active qubits for n times.
Yao.Registers.measure_remove! — Method.measure_remove!(register)measure the active qubits of this register and remove them.
Yao.Registers.register — Function.register([type], bit_str, [nbatch=1]) -> DefaultRegisterReturns a DefaultRegister by inputing a bit string, e.g
using Yao
register(bit"0000")Yao.Registers.register — Method.register(raw) -> DefaultRegisterReturns 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) -> FunctionInverse transformation of focus, with nbit is the number of active bits of target register.
Yao.Registers.stack — Method.stack(regs::DefaultRegister...) -> DefaultRegisterstack multiple registers into a batch.
Yao.Registers.statevec — Function.statevec(r::AbstractRegister) -> AbstractArrayReturn the raveled state (vector) form of this register.
Yao.Registers.tracedist — Function.tracedist(reg1::DefaultRegister, reg2::DefaultRegister) -> Vector
tracedist(reg1::DensityMatrix, reg2::DensityMatrix) -> Vectortrace distance.
Yao.Registers.ρ — Function.ρ(register)Returns the density matrix of this register.
Yao.Registers.QuBitStr — Type.QuBitStrString literal for qubits.
Base.LinAlg.normalize! — Method.normalize!(r::AbstractRegister) -> AbstractRegisterReturn the register with normalized state.
Base.kron — Method.kron(lhs, rhs)Merge two registers together with kronecker tensor product.
Yao.Registers.shapeorder — Method.Get the compact shape and order for permutedims.