# Quick Start

In this quick start, we list several common use cases for Yao before you go deeper into the manual.

## Create a quantum register/state

A register is an object that describes a device with an internal state. See Registers for more details. Yao use registers to represent quantum states. The most common register is the `ArrayReg`

, you can create it by feeding a state vector to it, e.g

`julia> using Yao`

`julia> ArrayReg(randn(ComplexF64, 2^3)) # a random unnormalized 3-qubit state`

`ArrayReg{2, ComplexF64, Array...} active qubits: 3/3 nlevel: 2`

`julia> zero_state(5) # |00000⟩`

`ArrayReg{2, ComplexF64, Array...} active qubits: 5/5 nlevel: 2`

`julia> rand_state(5) # a random state`

`ArrayReg{2, ComplexF64, Array...} active qubits: 5/5 nlevel: 2`

`julia> product_state(bit"10100") # |10100⟩`

`ArrayReg{2, ComplexF64, Array...} active qubits: 5/5 nlevel: 2`

`julia> ghz_state(5) # (|00000⟩ + |11111⟩)/√2`

`ArrayReg{2, ComplexF64, Array...} active qubits: 5/5 nlevel: 2`

the internal quantum state can be accessed via `statevec`

method

`julia> statevec(ghz_state(2))`

`4-element Vector{ComplexF64}: 0.7071067811865476 - 0.0im 0.0 + 0.0im 0.0 + 0.0im 0.7071067811865476 - 0.0im`

for more functionalities about registers please refer to the manual of Registers.

## Create quantum circuit

Yao introduces an abstract representation for linear maps, called "block"s, which can be used to represent quantum circuits, Hamiltonians, and other quantum operations. The following code creates a 2-qubit circuit

`julia> chain(2, put(1=>H), put(2=>X))`

`nqubits: 2 chain ├─ put on (1) │ └─ H └─ put on (2) └─ X`

where `H`

gate is at 1st qubit, `X`

gate is at 2nd qubit. A more advanced example is the quantum Fourier transform circuit

`julia> A(i, j) = control(i, j=>shift(2π/(1<<(i-j+1)))) # a cphase gate`

`A (generic function with 1 method)`

`julia> B(n, k) = chain(n, j==k ? put(k=>H) : A(j, k) for j in k:n)`

`B (generic function with 1 method)`

`julia> qft(n) = chain(B(n, k) for k in 1:n)`

`qft (generic function with 1 method)`

`julia> circuit = qft(3) # a 3-qubit QFT circuit`

`nqubits: 3 chain ├─ chain │ ├─ put on (1) │ │ └─ H │ ├─ control(2) │ │ └─ (1,) shift(1.5707963267948966) │ └─ control(3) │ └─ (1,) shift(0.7853981633974483) ├─ chain │ ├─ put on (2) │ │ └─ H │ └─ control(3) │ └─ (2,) shift(1.5707963267948966) └─ chain └─ put on (3) └─ H`

`julia> mat(circuit) # the matrix representation of the circuit`

`8×8 SparseMatrixCSC{ComplexF64, Int64} with 64 stored entries: 0.353553+0.0im 0.353553+0.0im … 0.353553+0.0im 0.353553+0.0im -0.353553+0.0im 0.25-0.25im 0.353553+0.0im 0.353553+0.0im -2.16489e-17-0.353553im 0.353553+0.0im -0.353553+0.0im -0.25-0.25im 0.353553+0.0im 0.353553+0.0im -0.353553+0.0im 0.353553+0.0im -0.353553+0.0im … -0.25+0.25im 0.353553+0.0im 0.353553+0.0im 2.16489e-17+0.353553im 0.353553+0.0im -0.353553+0.0im 0.25+0.25im`

`julia> apply!(zero_state(3), circuit) # apply the circuit to a zero state`

`ArrayReg{2, ComplexF64, Array...} active qubits: 3/3 nlevel: 2`

More details about available blocks can be found in the manual of Blocks.

## Create Hamiltonian

We can create a simple Ising Hamiltonian on 1D chain as following

`julia> h = sum([kron(5, i=>Z, mod1(i+1, 5)=>Z) for i in 1:5]) # a 5-qubit Ising Hamiltonian`

`nqubits: 5 + ├─ kron │ ├─ 1=>Z │ └─ 2=>Z ├─ kron │ ├─ 2=>Z │ └─ 3=>Z ├─ kron │ ├─ 3=>Z │ └─ 4=>Z ├─ kron │ ├─ 4=>Z │ └─ 5=>Z └─ kron ├─ 1=>Z └─ 5=>Z`

`julia> mat(h) # the matrix representation of the Hamiltonian`

`32×32 Diagonal{ComplexF64, Vector{ComplexF64}}: 5.0+0.0im ⋅ ⋅ … ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ … ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋮ ⋱ ⋮ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ … ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ … ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 5.0-0.0im`

## Differentiating a quantum circuit

Yao has its own automatic differentiation rule implemented, this allows one obtain gradients of a loss function by simply putting a `'`

mark following `expect`

or `fidelity`

, e.g

To obtain the gradient of the quantum Fourier transform circuit with respect to its parameters, one can use the following code

`julia> grad_state, grad_circuit_params = expect'(kron(X, X, I2) + kron(I2, X, X), zero_state(3)=>qft(3))`

`ArrayReg{2, ComplexF64, Array...} active qubits: 3/3 nlevel: 2 => Any[0.0, 0.0, 0.0]`

where `kron(X, X, I2) + kron(I2, X, X)`

is the target Hamiltonian, `zero_state(3)`

is the initial state, `qft(3)`

is the quantum Fourier transform circuit. The return value is a vector, each corresponding to the gradient of the loss function with respect to a parameter in the circuit. The list of parameters can be obtained by `parameters`

function.

`julia> parameters(qft(3))`

`3-element Vector{Float64}: 1.5707963267948966 0.7853981633974483 1.5707963267948966`

To obtain the gradient of the fidelity between a state parameterized by a quantum circuit and a target state, one can use the following code

`julia> ((grad_state1, grad_circuit1), grad_state2) = fidelity'(zero_state(3)=>qft(3), ghz_state(3))`

`(ArrayReg{2, ComplexF64, Array...} active qubits: 3/3 nlevel: 2 => Any[0.0, 0.0, 0.0], ArrayReg{2, ComplexF64, Array...} active qubits: 3/3 nlevel: 2)`

where `zero_state(3)`

is the initial state, `qft(3)`

is the quantum Fourier transform circuit, `ghz_state(3)`

is the target state.

The automatic differentiation functionality can also be accessed by interfacing with the machine learning libraries `Zygote`

.

## Plot quantum circuits

The component package `YaoPlots`

provides plotting for quantum circuits and ZX diagrams. You can use it to visualize your quantum circuits in `VSCode`

, `Jupyter`

notebook or `Pluto`

notebook.

```
using Yao.EasyBuild, Yao.YaoPlots
using Compose
# show a qft circuit
vizcircuit(qft_circuit(5))
```

More details about the plotting can be found in the manual: Quantum Circuit Visualization.