Git Product home page Git Product logo

Comments (5)

Roger-luo avatar Roger-luo commented on July 19, 2024

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 from pos.
function apply(gate::AbstractGate{N}, state) where N end
  • apply the gate to given state on the first N qubit (equals to pos=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 with N legs) to contract with blocks/gates inside this BasicBlock

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.

Roger-luo avatar Roger-luo commented on July 19, 2024

List some reference and resources here:

from yao.jl.

Roger-luo avatar Roger-luo commented on July 19, 2024

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 a Sequence block, this is a naive wrapper of a list of blocks. (no shape check)
  • chain(blocks...): chain several blocks together, it returns a ChainBlock and requires all its ninput and noutput is equal. See ChainBlock for more info.
  • kron(blocks...) or kron(block_with_pos::Tuple{Int, Block}...): combine serveal block together by kronecker product. See KronBlock for more info.
  • cache(block, level=1): cache its argument with a cache level. See CacheBlock 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 is N)
  • noutput: number of output qubits (default is N)
  • isunitary: check whether this block type is a unitary (default is false)
  • iscacheable: check whether this block type is cacheable (default is false)
  • cache_type: what kind of cache block (with which level) should be used for this block (default is CacheBlock)
  • ispure: check whether this block type is a pure block (default is false)

Instance Properties

  • get_cache(block)->list: get all cache blocks in block

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, unless force=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 is true)

Instance Properties

  • full: get the dense matrix form of given instance
  • sparse: 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 of Concentrator

Sequence

a naive wrapper of a sequence of blocks.

struct Sequence{N} <: AbstractBlock{N}
    list::Vector
end

Exported

  • sequence(blocks...): create an instance of Sequence.

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's cache_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 of ChainBlock 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) and kron(blocks_with_pos::Tuple...) create an instance of KronBlock

PrimitiveBlock

abstract supertype which all primitive blocks will inherit from.

Prototype

abstract type PrimitiveBlock{N} <: PureBlock{N} end

Type Traits

  • iscacheable: default is true
  • isunitary: default is true

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.

GiggleLiu avatar GiggleLiu commented on July 19, 2024

RotationBlock is not PrimitiveBlock, it is consist of single qubit arbitrary rotation blocks.

from yao.jl.

Roger-luo avatar Roger-luo commented on July 19, 2024

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.