QuantumBFS / Yao.jl

Extensible, Efficient Quantum Algorithm Design for Humans.
https://yaoquantum.org
Other
924 stars 123 forks source link

ROADMAP: Plans for what to support in v0.1 #1

Closed Roger-luo closed 6 years ago

Roger-luo commented 6 years ago

This issue is for listing what shoud be support in the first version.

Roger-luo commented 6 years ago

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)
sparse(gate)
full(gate)
function apply(gate, state, pos) end
function apply(gate::AbstractGate{N}, state) where N end
function update!(gate, params) end

Overloaded operators

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)

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

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

Two Qubits

Control Gates

Blocks

Blocks are conbination of multiple gates on multiple qubits.

Roger-luo commented 6 years ago

List some reference and resources here:

Roger-luo commented 6 years ago

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

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

Instance Properties

Required Methods

PureBlock

Abstract block supertype whose subtype has a square matrix form.

Prototype:

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

Type Traits

Instance Properties

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

Instance Properties

Required Methods

Sequence

a naive wrapper of a sequence of blocks.

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

Exported

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

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

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

PrimitiveBlock

abstract supertype which all primitive blocks will inherit from.

Prototype

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

Type Traits

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:

PhiGate: block for phase gates

mutable struct PhiGate{T} <: PrimitiveBlock{1}
    theta::T
end

Exported bindings

Rotation: a primitive block for rotation gates (not RotationBlock)

mutable struct Rotation{GT, T} <: PrimitiveBlock{1}
    theta::T
end

Exported bindings

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

GiggleLiu commented 6 years ago

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

Roger-luo commented 6 years ago

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),
)