Blocks System

Blocks System

Blocks are the basic component of a quantum circuit in Yao.

Block System

The whole framework is consist of a block system. The whole system characterize a quantum circuit into serveral kinds of blocks. The uppermost abstract type for the whole system is AbstractBlock


Composite Blocks


Roller is a special pattern of quantum circuits. Usually is equivalent to a KronBlock, but we can optimize the computation by rotate the tensor form of a quantum state and apply each small block on it each time.




abstract type that all block will subtype from. N is the number of qubits.

Required interfaces * apply! or (and) mat

Interfaces for parametric blocks.

* iparameters
* setiparameters
ContainerBlock{N, T} <: MatrixBlock{N, T}

abstract supertype which container blocks will inherit from.

extended APIs

block: the block contained by this ContainerBlock

AbstractMeasure <: AbstractBlock

Abstract block supertype which measurement block will inherit from.

AbstractScale{N, T} <: TagBlock{N, T}

Block for scaling siblings by a factor of X.

AddBlock{N, T} <: CompositeBlock{N, T}

Adding multiple blocks into one.

BPDiff{GT, N, T, PT} <: AbstractDiff{GT, N, Complex{T}}
BPDiff(block, [grad]) -> BPDiff

Mark a block as differentiable, here GT, PT is gate type, parameter type.

Warning: please don't use the adjoint after BPDiff! adjoint is reserved for special purpose! (back propagation)


Iterate through the whole block tree with breadth first search.

CacheFragment{BT, K, MT}

A fragment that will be stored for each cached block (of type BT) on a cache server.

CachedBlock{ST, BT, N, T} <: TagBlock{N, T}

A label type that tags an instance of type BT. It forwards every methods of the block it contains, except mat and apply!, it will cache the matrix form whenever the program has.

ChainBlock{N, T} <: CompositeBlock{N, T}

ChainBlock is a basic construct tool to create user defined blocks horizontically. It is a Vector like composite type.

CompositeBlock{N, T} <: MatrixBlock{N, T}

abstract supertype which composite blocks will inherit from.

extended APIs

blocks: get an iteratable of all blocks contained by this CompositeBlock

Concentrator{N, T, BT <: AbstractBlock} <: AbstractContainer{N, T}

concentrates serveral lines together in the circuit, and expose it to other blocks.

ConstantGate{N, T} <: PrimitiveBlock{N, T}

Abstract type for constant gates.

ControlBlock{N, BT<:AbstractBlock, C, M, T} <: AbstractContainer{N, T}

N: number of qubits, BT: controlled block type, C: number of control bits, T: type of matrix.

Daggered{N, T, BT} <: TagBlock{N, T}

Daggered{N, T, BT}(blk)

Daggered Block.

FunctionBlock <: AbstractBlock

This block contains a general function that perform an in-place operation over a register

KronBlock{N, T, MT<:MatrixBlock} <: CompositeBlock{N, T}

composite block that combine blocks by kronecker product.

MathBlock{L, N, T} <: PrimitiveBlock{N, T}

Block for arithmatic operations, the operation name can be specified by type parameter L. Note the T parameter represents the kind of view of basis (the input format of func), which should be one of bint, bint_r, bfloat, bfloat_r.

MatrixBlock{N, T} <: AbstractBlock

abstract type that all block with a matrix form will subtype from.

Measure <: AbstractMeasure
Measure() -> Measure

Measure block, collapse a state and store measured value, e.g.


julia> m = Measure();

julia> reg = product_state(4, 7)
DefaultRegister{1, Complex{Float64}}
    active qubits: 4/4

julia> reg |> m
DefaultRegister{1, Complex{Float64}}
    active qubits: 4/4

julia> m.result
1-element Array{Int64,1}:

Note: Measure returns a vector here, the length corresponds to batch dimension of registers.

MeasureAndRemove <: AbstractMeasure
MeasureAndRemove() -> MeasureAndRemove

Measure and remove block, remove measured qubits and store measured value.

MeasureAndReset <: AbstractMeasure
MeasureAndReset([val=0]) -> MeasureAndReset

Measure and reset block, reset measured qubits to val and store measured value.


Global phase gate.

PrimitiveBlock{N, T} <: MatrixBlock{N, T}

abstract type that all primitive block will subtype from. A primitive block is a concrete block who can not be decomposed into other blocks. All composite block can be decomposed into several primitive blocks.

NOTE: subtype for primitive block with parameter should implement hash and == method to enable key value cache.

PutBlock{N, C, GT, T} <: AbstractContainer{N, T}

put a block on given addrs.

QDiff{GT, N, T} <: AbstractDiff{GT, N, Complex{T}}
QDiff(block) -> QDiff

Mark a block as quantum differentiable.

ReflectBlock{N, T} <: PrimitiveBlock{N, T}

Householder reflection with respect to some target state, $|\psi\rangle = 2|s\rangle\langle s|-1$.

RepeatedBlock{N, C, GT, T} <: AbstractContainer{N, T}

repeat the same block on given addrs.

Roller{N, T, BT} <: CompositeBlock{N, T}

map a block type to all lines and use a rolling method to evaluate them.


fill identity like KronBlock -> To interface.

RotationGate{N, T, GT <: MatrixBlock{N, Complex{T}}} <: PrimitiveBlock{N, Complex{T}}

RotationGate, with GT both hermitian and isreflexive.

Scale{BT, FT, N, T} <: AbstractScale{N, T}

Scale(block, factor) -> Scale

Scale Block.

Sequential <: AbstractBlock

sequencial structure that looser than a chain, it does not require qubit consistency and does not have mat method.

ShiftGate <: PrimitiveBlock

Phase shift gate.

StaticScale{X, BT, N, T} <: AbstractScale{N, T}

StaticScale{X, N, T, BT}(blk::MatrixBlock)

Scale Block, by a static factor of X, notice X is static!

TagBlock{N, T} <: AbstractContainer{N, T}

TagBlock is a special kind of Container, it is a size keeper.

TimeEvolution{N, TT, GT} <: PrimitiveBlock{N, ComplexF64}

TimeEvolution(H::GT, t::TT; tol::Real=1e-7) -> TimeEvolution

TimeEvolution, where GT is block type. input matrix should be hermitian.

apply!(reg, block, [signal])

apply a block to a register reg with or without a cache signal.

applymatrix(g::AbstractBlock) -> Matrix

Transform the apply! function of specific block to dense matrix.

backward!(δ::AbstractRegister, circuit::MatrixBlock) -> AbstractRegister

back propagate and calculate the gradient ∂f/∂θ = 2Re(∂f/∂ψ⋅∂ψ/∂θ), given ∂f/∂ψ.

Note: Here, the input circuit should be a matrix block, otherwise the back propagate may not apply (like Measure operations).

block(container::AbstractContainer) -> AbstractBlock

get the contained block (i.e. subblock) of a container.

blockfilter(func, blk::AbstractBlock) -> Vector{AbstractBlock}
blockfilter!(func, rgs::Vector, blk::AbstractBlock) -> Vector{AbstractBlock}

tree wise filtering for blocks.

chblock(block, blk)

change the block of a container.

chfactor(blk::AbstractScale) -> AbstractScale

change scaling factor of blk.

chsubblocks(pb::AbstractBlock, blks) -> AbstractBlock

Change subblocks of target block.

dispatch!!([func::Function], block::AbstractBlock, params) -> AbstractBlock

Similar to dispatch!, but will pop! out params inplace, it can not more efficient.

dispatch!([func::Function], block::AbstractBlock, params) -> AbstractBlock
dispatch!([func::Function], block::AbstractBlock, :random) -> AbstractBlock
dispatch!([func::Function], block::AbstractBlock, :zero) -> AbstractBlock

dispatch! parameters into this circuit, here params is an iterable.

If instead of iterable, a symbol :random or :zero is provided, random numbers (its behavior is specified by setiparameters!) or 0s will be broadcasted into circuits.

using dispatch!! is more efficient, but will pop! out all params inplace.

expect(op::AbstractBlock, reg::AbstractRegister{B}) -> Vector
expect(op::AbstractBlock, dm::DensityMatrix{B}) -> Vector

expectation value of an operator.

factor(blk::AbstractScale) -> Number

get scaling factor of blk.

generator(rot::Rotor) -> MatrixBlock

Return the generator of rotation block.

gradient(circuit::AbstractBlock, mode::Symbol=:ANY) -> Vector

collect all gradients in a circuit, mode can be :BP/:QC/:ANY, they will collect grad from BPDiff/QDiff/AbstractDiff respectively.

iparameter_type(block::AbstractBlock) -> Type

element type of iparameters(block).

iparameters(block) -> Vector

Returns a list of all intrinsic (not from sublocks) parameters in block.

mat(block) -> Matrix

Returns the matrix form of this block.

niparameters(x) -> Integer

Returns the number of parameters of x.

nparameters(c::AbstractBlock) -> Int

number of parameters, including parameters in sublocks.

parameter_type(block) -> Type

the type of iparameters.

parameters(c::AbstractBlock, [output]) -> Vector

get all parameters including sublocks.

setparameters!([elementwisefunction], r::AbstractBlock, params::Number...) -> AbstractBlock
setparameters!([elementwisefunction], r::AbstractBlock, :random) -> AbstractBlock
setparameters!([elementwisefunction], r::AbstractBlock, :zero) -> AbstractBlock

set intrinsics parameter for block, input params can be numbers or :random or :zero.

subblocks(blk::AbstractBlock) -> Tuple

return a tuple of all sub-blocks in this block.

traverse(blk; algorithm=:DFS) -> BlockTreeIterator

Returns an iterator that traverse through the block tree.

addrs(block::AbstractBlock) -> Vector{Int}

Occupied addresses (include control bits and bits occupied by blocks), fall back to all bits if this method is not provided.

isreflexive(x) -> Bool

Test whether this operator is reflexive.

isunitary(x) -> Bool

Test whether this operator is unitary.

datatype(x) -> DataType

Returns the data type of x.

nqubits(::Type{MT}) -> Int
nqubits(::MatrixBlock) -> Int

Return the number of qubits of a MatrixBlock.

collect(circuit::AbstractBlock, ::Type{BT}) where BT<:AbstractBlock

collect blocks of type BT in the block tree with circuit as root.

all blocks are matrix blocks

promote types of blocks


Returns the key that identify the matrix cache of this block. By default, we use the returns of parameters as its key.

cache_type(::Type) -> DataType

A type trait that defines the element type that a CacheFragment will use.

istraitkeeper(block) -> Bool

change the block of a container.

print_block(io, block)

define the style to print this block

render_params(r::AbstractBlock, raw_parameters) -> Iterable

More elegant way of rendering parameters for symbols.

@const_gate NAME = MAT_EXPR
@const_gate NAME::Type = MAT_EXPR
@const_Gate NAME::Type

This macro simplify the definition of a constant gate. It will automatically bind the matrix form to a constant which will reduce memory allocation in the runtime.

@const_gate X = ComplexF64[0 1;1 0]


@const_gate X::ComplexF64 = [0 1;1 0]

You can bind new element types by simply re-declare with a type annotation.

@const_gate X::ComplexF32