Comments (5)
In general, this package will use a block tree to store the structure of a quantum circuit. Each block is a quantum gate with index.
Interface of Quantum Gate
Abstract type:
abstract type AbstractGate{N} end
required functions of Interface
size(gate)
- get the size of this gate (number of qubits), this overloads the interface in
Base
sparse(gate)
- get the sparse matrix form of the given gate, this overloads the interface in
stdlib
full(gate)
- get the dense matrix form of the given gate, this overloads the interface in
stdlib
function apply(gate, state, pos) end
- apply the
N
qubits gate on the qubits start frompos
.
function apply(gate::AbstractGate{N}, state) where N end
- apply the gate to given state on the first
N
qubit (equals topos=1
)
function update!(gate, params) end
- update parameters inside a parameterized gate, this method use a different name because this operation has side-effect on the given gate.
Overloaded operators
- call methods, call methods is equivalent to interface
apply
. We should follow: explicit is better than implicit
function (::AbstractGate)(state, pos) end
function (::AbstractGate)(state) end
Additional Interface of Block
Blocks are subtypes of AbstractGate
with additional information about its position in a quantum circuit, it is a container of subtypes of AbstractGate
. The final structure will looks similar to Julia's own AST tree.
abstract type AbstractBlock{N} <: AbstractGate{N} end
Required functions
apply(block, state)
- since we have information about which qubit to apply, the interface of the
apply
method will be changed to the above form.
Generic Block
Generic Block will not be type stable since this will store any possible instance of the subtypes of AbstractBlock
.
mutable struct BasicBlock{N} <: AbstractBlock{N}
heads::Vector{Int}
lists::Vector{AbstractBlock}
end
function apply(gate::BasicBlock, state) end
apply
method will reshape the state (a tensor withN
legs) to contract with blocks/gates inside thisBasicBlock
Rotation Block
The structure is known for a rotation block:
-- [Z] -- [X] -- [Z] --
...
-- [Z] -- [X] -- [Z] --
we don't actually need to store what's inside there
struct RotationBlock{N} <: AbstractBlock{N}
end
and we assume a rotation block is contiguous on quantum register, and for rotation operations like
-- [Z] -- [X] -- [Z] --
...
-- [Z] -- [X] -- [Z] --
-----------------------
-- [Z] -- [X] -- [Z] --
...
-- [Z] -- [X] -- [Z] --
Then we will have two rotation blocks.
List of Types
What will be included in our first version (v0.0.1) is listed below.
Single Qubit
- Pauli Gates: X, Y, Z (v0.0.1)
- Phase Gates: S, T (pi/8 gate) (v0.0.1)
- Rotation Gates: Rx, Ry, Rz (v0.0.1)
Two Qubits
Control Gates
- Controlled NOT: CNOT (v0.0.1)
- Controlled Gate (v0.0.1)
Blocks
Blocks are conbination of multiple gates on multiple qubits.
- Rotation Block (v0.0.1)
- Time Evolution
- QFT Block
from yao.jl.
List some reference and resources here:
- PHYS4071
- The preparation of states in quantum mechanics
- Realization of the quantum Toffoli gate
- Caltech lecture notes
from yao.jl.
Proposal for blocks
Demo
Native circuit construction.
circuit = chain(
kron(Hardmard for i=1:4),
focus(4, 1:2),
PauliX,
focus(4, 1:4)
control(
4, PauliX,
1, 2, 3,
),
focus(4, 1:2),
PauliX,
# 1:3 active now
focus(4, 1:3),
kron(chain(Hardmard, PauliX) for i=1:3),
control(
3, PauliZ,
1, 2,
)
kron(chain(PauliX, Hardmard) for i=1:3),
)
Accelerate circuit evaluation with cached blocks
With its matrix form cached blocks, the process of evaluation can be accelerated
with directly calculation with its matrix form.
# A four qubit quantum circuit born machine
rotations = [rotation(4), rotation(4)]
circuit = sequence(
cache(rotations[1], level=3),
cache(
kron(
control(
2, PauliX,
1,
),
control(
2, PauliX,
1,
),
),
level=1
),
focus(4, 1:3),
control(
1, PauliX,
2, 3,
)
focus(4, 1:4),
cache(rotations[2], level=3),
measure(1:4, n=1000)
)
register = Register(4)
step = 1e-2
# force cache all cacheable block in the beginning
cache!(circuit, force=true)
# this trains the first rotation block
for i in 1:1000
update!(rotations[1], (i%4, -pi/2)) # update will add parameters
cache!(circuit) # will not re-cache next time
negative = circuit(register)
update!(rotations[1], (i%4, pi/2))
cache!(circuit)
positive = circuit(register)
grad = grad_MMD_loss(negative, positive)
update!(rotations[1], (i%4, grad * step))
end
Different measurements
# A four qubit quantum circuit born machine
rotations = [rotation(4), rotation(4)]
pre_circuit = chain(
cache(rotations[1], level=3),
cache(
kron(
control(
2, PauliX,
1,
),
control(
2, PauliX,
1,
),
),
level=1
),
focus(4, 1:3),
control(
1, PauliX,
2, 3,
)
focus(4, 1:4),
cache(rotations[2], level=3)
)
post_circuit = sequence(
pre_circuit,
remove!(4, 1:2), # this create a `RemoveBlock` (a subtype of `AbstractMeasure`)
another_smaller_circuit,
)
Types & Interface
Methods for circuit construction
sequence(blocks...)
: make aSequence
block, this is a naive wrapper of a list of blocks. (no shape check)chain(blocks...)
: chain several blocks together, it returns aChainBlock
and requires all itsninput
andnoutput
is equal. SeeChainBlock
for more info.kron(blocks...)
orkron(block_with_pos::Tuple{Int, Block}...)
: combine serveal block together by kronecker product. SeeKronBlock
for more info.cache(block, level=1)
: cache its argument with a cache level. SeeCacheBlock
for more info.control(head, block, control_qubits...)
: create a controled block
NOTE: All constructors of blocks will not be exported.
AbstractBlock
Abstract block supertype which blocks inherit from.
Prototype
abstract type AbstractBlock{N} end
Type Traits
ninput
: number of input qubits (default isN
)noutput
: number of output qubits (default isN
)isunitary
: check whether this block type is a unitary (default isfalse
)iscacheable
: check whether this block type is cacheable (default isfalse
)cache_type
: what kind of cache block (with which level) should be used for this block (default isCacheBlock
)ispure
: check whether this block type is a pure block (default isfalse
)
Instance Properties
get_cache(block)->list
: get all cache blocks inblock
Required Methods
apply!(register, block)->reg
: apply this block to a register, it will only have side-effect on this register.update!(block, params...)->block
: scatter a set of parameters to each block, it will only have side-effect on this block (and its children).cache!(block, level=1, force=false)->block
: update cache blocks with cache level less than input cache level, if there is a cached instance of block, unlessforce=true
, cache will not be updated.
PureBlock
Abstract block supertype whose subtype has a square matrix form.
Prototype:
abstract type PureBlock{N} <: AbstractBlock{N} end
Type Traits
ispure
: check whether this block type is a pure block (default istrue
)
Instance Properties
full
: get the dense matrix form of given instancesparse
: get the sparse matrix form of given instance
Required Methods
Concentrator
Block that concentrate given lines together.
Prototype:
struct Concentrator{N, M} <: AbstractBlock{N}
line_orders::NTuple{M, Int}
end
M
: number of active qubits.
Type Traits
ninput
: get the number of input qubits (N
)noutput
: get the number of output qubits (M
)
Instance Properties
line_orders
: get what is concentrated together
Required Methods
focus(nqubits, orders...)
: get a instance ofConcentrator
Sequence
a naive wrapper of a sequence of blocks.
struct Sequence{N} <: AbstractBlock{N}
list::Vector
end
Exported
sequence(blocks...)
: create an instance ofSequence
.
AbstractMeasure
Abstract block supertype which measurement block will inherit from.
Prototype
abstract type AbstractMeasure{N, M} <: AbstractBlock{N} end
CacheBlock
abstract supertype which cache blocks will inherit from
Prototype
abstract type CacheBlock{N} <: PureBlock{N} end
Method
cache!(block, level=1, force=false)
cache this block with given cache level.cache(block)
create a cache block according to this block type'scache_type
trait.
Subtype of PureBlock
CompositeBlock
abstract supertype which composite blocks will inherit from.
Prototype
abstract type CompositeBlock{N} <: PureBlock{N} end
Subtypes
ChainBlock
: chain a list of blocks together, will check its input and output shape.
struct ChainBlock{N, T <: AbstractBlock{N}}
list::Vector{T}
end
Exported bindings
chain(blocks...)
: create an instance ofChainBlock
and check the shape of each block. (ChainBlock
's constructor won't check the shape)
KronBlock
: fuse a list of blocks together with kronecker product
struct KronBlock{N, T <: PureBlock} <: AbstractBlock{N}
heads::Vector{Int}
list::Vector{T}
end
exported bindings
kron(blocks)
andkron(blocks_with_pos::Tuple...)
create an instance ofKronBlock
PrimitiveBlock
abstract supertype which all primitive blocks will inherit from.
Prototype
abstract type PrimitiveBlock{N} <: PureBlock{N} end
Type Traits
iscacheable
: default istrue
isunitary
: default istrue
Subtypes
Gate
: block for simple gate type (GT
) without parameters. Their matrix form is a constant matrix. Therefore, there will only be one matrix allocation no matter how many instances are created.
struct Gate{GT, N} <: PrimitiveBlock{N} end
Exported bindings:
PauliX, PauliY, PauliZ
Hardmard
CNOT
PhiGate
: block for phase gates
mutable struct PhiGate{T} <: PrimitiveBlock{1}
theta::T
end
Exported bindings
phase(theta)
Rotation
: a primitive block for rotation gates (not RotationBlock
)
mutable struct Rotation{GT, T} <: PrimitiveBlock{1}
theta::T
end
Exported bindings
rotation(::Type{GT}, ::AbstractFloat) where {GT <: Union{X, Y, Z}}
RotationBlock
: a primitive block for arbitrary rotation: Rz Rx Rz
mutable struct RotationBlock{N, T} <: PrimitiveBlock{N}
thetas::Vector{T} # 3N thetas
end
Exported bindings
rotation(::Int)
from yao.jl.
RotationBlock is not PrimitiveBlock, it is consist of single qubit arbitrary rotation blocks.
from yao.jl.
Then we can just use a KronBlock
with a ChainBlock
. But if there is any specific optimization for this we can always define a PrimitiveBlock
for this architecture.
kron( chain(Rz(), Rx(), Rz()) for i = 1:N )
or
chain(
kron(Rz() for i = 1:N),
kron(Rx() for i = 1:N),
kron(Rz() for i = 1:N),
)
from yao.jl.
Related Issues (20)
- More efficient implementation of `two_qubit_depolarizing_channel()` HOT 7
- Using Yao.jl in my paper "Using the Julia framework to teach quantum entanglement" HOT 2
- Python Interface HOT 2
- QRNG HOT 1
- `dispatch!(circuit, angles)` fails when gates are created with `Irrational` angles HOT 3
- dispatch(Ry(0), :random) is not working correctly HOT 1
- H not working HOT 2
- How to run a random circuite in a batched way? HOT 4
- How to import Yao.jl into IBM Qiskit Python code?
- Quantum circuit from MPS HOT 5
- Can't calculate `von_neumann_entropy()` in gpu HOT 2
- Update compat for `BitBasis` to 0.9 HOT 1
- solving pde using quantum differentiable circuits
- Reduce the compiling time of the repeat constructor
- CUDA is listed as a wrong compat
- Undesired handling of complex values when the expectation of an observable has zero real part HOT 3
- Measure block acts differently on cpu registers and cuda registers
- Precompiling CuYao Error in Julia 1.10.4 HOT 1
- Converting between KronBlock, Scale, and Add Objects HOT 4
- Add ExponentialUtilities backend back
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from yao.jl.