From 58e1effb5c4c0413b9ae3f7be8633530e61dacc4 Mon Sep 17 00:00:00 2001 From: GiggleLiu Date: Tue, 12 Mar 2024 20:39:31 +0800 Subject: [PATCH] update docs --- docs/src/assets/images/Riemannian.png | Bin 0 -> 56467 bytes .../8.riemannian-gradient-flow/main.jl | 31 +-- docs/src/man/registers.md | 210 ++++++++++++++---- docs/src/man/symbolic.md | 17 +- docs/src/quick-start.md | 61 ++--- lib/YaoArrayRegister/src/density_matrix.jl | 2 +- 6 files changed, 231 insertions(+), 90 deletions(-) create mode 100644 docs/src/assets/images/Riemannian.png diff --git a/docs/src/assets/images/Riemannian.png b/docs/src/assets/images/Riemannian.png new file mode 100644 index 0000000000000000000000000000000000000000..7a46dc10d34f3b17d0eb797f7dc3f58c97a8ed8f GIT binary patch literal 56467 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 J@gGiC{tF^nglYf) literal 0 HcmV?d00001 diff --git a/docs/src/examples/8.riemannian-gradient-flow/main.jl b/docs/src/examples/8.riemannian-gradient-flow/main.jl index 50429fd2..93d1bcf6 100644 --- a/docs/src/examples/8.riemannian-gradient-flow/main.jl +++ b/docs/src/examples/8.riemannian-gradient-flow/main.jl @@ -125,20 +125,25 @@ end; # Finally, let's try it out. # We initialize the state ``|0\rangle`` and apply several optimization steps. -circuit = chain(n) -pauli_strings = generate_2local_pauli_strings(n) -history = Float64[] - -for i=1:100 - cost = step_and_cost!(n, circuit, h, 0.01, pauli_strings) - push!(history, cost) -end - -Plots.plot(history, legend=false) -Plots.plot!(1:100, [w[1] for i=1:100]) -xlabel!("steps") -ylabel!("energy") +# ```julia +# circuit = chain(n) +# pauli_strings = generate_2local_pauli_strings(n) +# history = Float64[] + +# for i=1:100 +# cost = step_and_cost!(n, circuit, h, 0.01, pauli_strings) +# push!(history, cost) +# end + +# Plots.plot(history, legend=false) +# Plots.plot!(1:100, [w[1] for i=1:100]) +# xlabel!("steps") +# ylabel!("energy") +# ``` +# ```@raw html +# Riemannian gradient flow +# ``` # When we compare the final states achieved with the Riemannian gradient flow # optimizer and with the standard VQE we can notice that the former has lower quality. # This is because the Riemannian gradient flow optimizer has only a local view of the cost landscape diff --git a/docs/src/man/registers.md b/docs/src/man/registers.md index e82e35a5..51c36f43 100644 --- a/docs/src/man/registers.md +++ b/docs/src/man/registers.md @@ -11,9 +11,163 @@ end # [Quantum Registers](@id registers) +## Constructing quantum states + A quantum register is a quantum state or a batch of quantum states. -`Yao` provides two types of quantum registers [`ArrayReg`](@ref) and [`BatchedArrayReg`](@ref). +Qubits in a Yao register can be active or inactive. +Only active qubits are visible to quantum operators, which enables applying quantum operators on a subset of qubits. +For example, Suppose we want to run a quantum Fourier transformation circuit of size 4 on qubits `(1, 3, 5, 7)` with the [`focus!`](@ref) function, +we first set these qubits to active qubits the rest to inactive, then we apply the circuit on the active qubits, and finally we switch back to the original configuration with the [`relax!`](@ref) function. + +`Yao` provides two types of quantum registers [`ArrayReg`](@ref) and [`BatchedArrayReg`](@ref). Both use matrices as the storage. +For example, for a quantum register with ``a`` active qubits, ``r`` remaining qubits and batch size ``b``, the storage is as follows. + +![](../assets/images/regstorage.svg) + +The first dimension of size ``2^a`` is for active qubits, only this subset of qubits are allowed to interact with quantum operators. Since we reshaped the state vector into a matrix, applying a quantum operator can be conceptually represented as a matrix-matrix multiplication. + +Various quantum states can be created with the following functions. +```@repl register +using Yao +reg = ArrayReg([0, 1, -1+0.0im, 0]) # a unnormalized Bell state |01⟩ - |10⟩ +statevec(reg) # a quantum state is represented as a vector +print_table(reg) +``` + +```@repl register +reg_zero = zero_state(3) # create a zero state |000⟩ +print_table(reg_zero) +``` +```@repl register +reg_rand = rand_state(ComplexF32, 3) # a random state +``` + +```@repl register +reg_uniform = uniform_state(ComplexF32, 3) # a uniform state +print_table(reg_uniform) +``` + +```@repl register +reg_prod = product_state(bit"110") # a product state +bit"110"[3] # the bit string is in little-endian format +print_table(reg_prod) +``` + +```@repl register +reg_ghz = ghz_state(3) # a GHZ state +print_table(reg_ghz) +von_neumann_entropy(reg_ghz, (1, 3)) / log(2) # entanglement entropy between qubits (1, 3) and (2,) +``` + +```@repl register +reg_rand3 = rand_state(3, nlevel=3) # a random qutrit state +reg_prod3 = product_state(dit"120;3") # a qudit product state, what follows ";" symbol denotes the number of levels +print_table(reg_prod3) +``` + +```@repl register +reg_batch = rand_state(3; nbatch=2) # a batch of 2 random qubit states +print_table(reg_batch) +reg_view = viewbatch(reg_batch, 1) # view the first state in the batch +print_table(reg_view) +``` + +```@repl register +reg = rand_state(3; nlevel=4, nbatch=2) +nqudits(reg) # the total number of qudits +nactive(reg) # the number of active qubits +nremain(reg) # the number of remaining qubits +nbatch(reg) # the batch size +nlevel(reg) # the number of levels of each qudit +basis(reg) # the basis of the register +focus!(reg, 1:2) # set on the first two qubits as active +nactive(reg) # the number of active qubits +basis(reg) # the basis of the register +relax!(reg) # set all qubits as active +nactive(reg) # the number of active qubits +reorder!(reg, (3,1,2)) # reorder the qubits + +reg1 = product_state(bit"111"); +reg2 = ghz_state(3); +fidelity(reg1, reg2) # the fidelity between two states +tracedist(reg1, reg2) # the trace distance between two states +``` + +## Arithmetic operations + +The list of arithmetic operations for [`ArrayReg`](@ref) include +* `+` +* `-` +* `*` +* `/` (scalar) +* `adjoint` + + +```@repl register +reg1 = rand_state(3) +reg2 = rand_state(3) +reg3 = reg1 + reg2 # addition +normalize!(reg3) # normalize the state +isnormalized(reg3) # check if the state is normalized +reg1 - reg2 # subtraction +reg1 * 2 # scalar multiplication +reg1 / 2 # scalar division +reg1' # adjoint +reg1' * reg1 # inner product +``` + +## Register operations +```@repl register +reg0 = rand_state(3) +append_qudits!(reg0, 2) # append 2 qubits +insert_qudits!(reg0, 2, 2) # insert 2 qubits at the 2nd position +``` + +Comparing with using matrix multiplication for quantum simulation, using specialized instructions are much faster and memory efficient. These instructions are specified with the [`instruct!`](@ref) function. + +```@repl register +reg = zero_state(2) +instruct!(reg, Val(:H), (1,)) # apply a Hadamard gate on the first qubit +print_table(reg) +``` + +## Measurement + +We use the [`measure!`](@ref) function returns the measurement outcome and collapses the state after the measurement. +We also have some "cheating" version [`measure`](@ref) that does not collapse states to facilitate classical simulation. + +```@repl register +measure!(reg0, 1) # measure the qubit, the state collapses +measure!(reg0) # measure all qubits +measure(reg0, 3) # measure the qubit 3 times, the state does not collapse (hacky) +reorder!(reg0, 7:-1:1) # reorder the qubits +measure!(reg0) +invorder!(reg0) # reverse the order of qubits +measure!(reg0) +measure!(RemoveMeasured(), reg0, 2:4) # remove the measured qubits +reg0 + +reg1 = ghz_state(3) +select!(reg1, bit"111") # post-select the |111⟩ state +isnormalized(reg1) # check if the state is normalized +``` + +## Density matrices + +```@repl register +reg = rand_state(3) +rho = density_matrix(reg) # the density matrix of the state +rand_density_matrix(3) # a random density matrix +completely_mixed_state(3) # a completely mixed state +partial_tr(rho, 1) # partial trace on the first qubit +purify(rho) # purify the state +von_neumann_entropy(rho) # von Neumann entropy +mutual_information(rho, 1, 2) # mutual information between qubits 1 and 2 +``` + +## API +The constructors and functions for quantum registers are listed below. ```@docs AbstractRegister AbstractArrayReg @@ -21,8 +175,6 @@ ArrayReg BatchedArrayReg ``` -We define some shortcuts to create simulated quantum states easier: - ```@docs arrayreg product_state @@ -34,12 +186,7 @@ ghz_state clone ``` -In a register, qubits are distinguished as active and inactive (or remaining). -The total number of qubits is the number of active qubits plus the number of remaining qubits. -Only active qubits are visible to quantum operators and the number of these qubits are the *size* of a register. -Making this distinction of qubits allows writing reusable quantum circuits. -For example, Suppose we want to run a quantum Fourier transformation circuit of size 4 on qubits `(1, 3, 5, 7)`, -we first set the target qubits to active qubits the reset to inactive, then we apply the circuit on it, finally we unset the inactive qubits. +The following functions are for querying the properties of a quantum register. ```@docs nqudits @@ -54,15 +201,7 @@ relax! exchange_sysenv ``` -## Storage - -Both [`ArrayReg`](@ref) and [`BatchedArrayReg`](@ref) use matrices as the storage. For example, for a quantum register with ``a`` active qubits, ``r`` remaining qubits and batch size ``b``, the storage is as follows - -![](../assets/images/regstorage.svg) - -The first dimension of size ``2^a`` is for active qubits, only this subset of qubits are allowed to interact with blocks. Since we reshaped the state vector into a matrix, applying a quantum operator can always be represented as a matrix-matrix multiplication . In practice, most gates have in-place implementation that does not require constructing the operator matrix explicitly. - -You can access different views of the storage of an [`ArrayReg`](@ref) with the following functions: +The following functions are for querying the state of a quantum register. ```@docs state @@ -75,23 +214,7 @@ viewbatch transpose_storage ``` -## Operations - -The list of arithmetic operations for [`ArrayReg`](@ref) include -* `+` -* `-` -* `*` -* `/` (scalar) -* `adjoint` - -Then the inner product can be computed as follows. - -```julia -julia> reg = rand_state(3); - -julia> reg' * reg -0.9999999999999998 + 0.0im -``` +The following functions are for arithmetic operations on quantum registers. ```@docs AdjointArrayReg @@ -112,7 +235,7 @@ fidelity tracedist ``` -## Resource management and addressing +The following functions are for adding and reordering qubits in a quantum register. ```@docs insert_qudits! @@ -123,22 +246,13 @@ reorder! invorder! ``` -Only a subset of qubits that does not interact with other qubits can be removed, the best approach is first measuring it in computational basis first. -It can be done with the [`measure!`](@ref) function by setting the first argument to `RemoveMeasured()`. - -## Instruction set - -Although we have matrix representation for Yao blocks, specialized instructions are much faster and memory efficient than using the matrix-matrix product. -These instructions are specified with the `instruct!` function listed bellow. +The `instruct!` function is for applying quantum operators on a quantum register. ```@docs YaoArrayRegister.instruct! ``` -## Measurement - -We have a true measure function `measure!` that collapses the state after the measurement. -We also have some "cheating" functions to facilitate classical simulation. +The following functions are for measurement and post-selection. ```@docs measure! @@ -150,7 +264,7 @@ probs most_probable ``` -## Density matrices +The following functions are for density matrices. ```@docs DensityMatrix diff --git a/docs/src/man/symbolic.md b/docs/src/man/symbolic.md index 8c3b4939..b8e67120 100644 --- a/docs/src/man/symbolic.md +++ b/docs/src/man/symbolic.md @@ -11,7 +11,22 @@ end # Symbolic Computation -Symbolic Computation support for Yao +The symbolic engine of Yao is based on [SymEngine.jl](https://github.com/symengine/SymEngine.jl). It allows one to define quantum circuits with symbolic parameters and perform symbolic computation on them. Two macro/functions play a key role in the symbolic computation: +- `@vars` for defining symbolic variables +- `subs` for substituting symbolic variables with concrete values + +```@repl sym +using Yao +@vars θ +circuit = chain(2, put(1=>H), put(2=>Ry(θ))) +mat(circuit) +new_circuit = subs(circuit, θ=>π/2) +mat(new_circuit) +``` + +## API + +The following functions are for working with symbolic states. ```@docs @ket_str diff --git a/docs/src/quick-start.md b/docs/src/quick-start.md index 9452a8a9..5807def6 100644 --- a/docs/src/quick-start.md +++ b/docs/src/quick-start.md @@ -11,11 +11,11 @@ is the [`ArrayReg`](@ref), you can create it by feeding a state vector to it, e. ```@repl quick-start using Yao -ArrayReg(rand(ComplexF64, 2^3)) -zero_state(5) -rand_state(5) -product_state(bit"10100") -ghz_state(5) +ArrayReg(randn(ComplexF64, 2^3)) # a random unnormalized 3-qubit state +zero_state(5) # |00000⟩ +rand_state(5) # a random state +product_state(bit"10100") # |10100⟩ +ghz_state(5) # (|00000⟩ + |11111⟩)/√2 ``` the internal quantum state can be accessed via [`statevec`](@ref) method @@ -26,10 +26,9 @@ statevec(ghz_state(2)) for more functionalities about registers please refer to the manual of [Registers](@ref registers). -## Create quantum circuit with Yao blocks +## Create quantum circuit -Yao uses the quantum "block"s to describe quantum circuits, e.g -the following code creates a 2-qubit 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 ```@repl quick-start chain(2, put(1=>H), put(2=>X)) @@ -39,48 +38,54 @@ where `H` gate is at 1st qubit, `X` gate is at 2nd qubit. A more advanced example is the quantum Fourier transform circuit ```@repl quick-start -A(i, j) = control(i, j=>shift(2π/(1<<(i-j+1)))) +A(i, j) = control(i, j=>shift(2π/(1<<(i-j+1)))) # a cphase gate B(n, k) = chain(n, j==k ? put(k=>H) : A(j, k) for j in k:n) qft(n) = chain(B(n, k) for k in 1:n) -qft(3) +circuit = qft(3) # a 3-qubit QFT circuit +mat(circuit) # the matrix representation of the circuit +apply!(zero_state(3), circuit) # apply the circuit to a zero state ``` -## Create Hamiltonian with Yao blocks +More details about available blocks can be found in the manual of [Blocks](@ref blocks). -the quantum "block"s are expressions on quantum operators, thus, it can -also be used to represent a Hamiltonian, e.g we can create a simple Ising -Hamiltonian on 1D chain as following +## Create Hamiltonian + +We can create a simple Ising Hamiltonian on 1D chain as following ```@repl quick-start -sum(kron(5, i=>Z, mod1(i+1, 5)=>Z) for i in 1:5) +h = sum([kron(5, i=>Z, mod1(i+1, 5)=>Z) for i in 1:5]) # a 5-qubit Ising Hamiltonian +mat(h) # the matrix representation of the Hamiltonian ``` -## Automatic differentiate a Yao block +## 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`](@ref) or [`fidelity`](@ref), e.g +To obtain the gradient of the quantum Fourier transform circuit with respect to its parameters, one can use the following code ```@repl quick-start -expect'(X, zero_state(1)=>Rx(0.2)) +grad_state, grad_circuit_params = expect'(kron(X, X, I2) + kron(I2, X, X), zero_state(3)=>qft(3)) ``` - -or for fidelity - +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`](@ref) function. ```@repl quick-start -fidelity'(zero_state(1)=>Rx(0.1), zero_state(1)=>Rx(0.2)) +parameters(qft(3)) ``` -## Combine Yao with ChainRules/Zygote - +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 -## Symbolic calculation with Yao block -Yao supports symbolic calculation of quantum circuit via `SymEngine`. We can show +```@repl quick-start +((grad_state1, grad_circuit1), grad_state2) = fidelity'(zero_state(3)=>qft(3), ghz_state(3)) +``` +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`](https://github.com/FluxML/Zygote.jl). ## Plot quantum circuits -The component package `YaoPlots` provides plotting for quantum circuits and ZX diagrams. +The component package `YaoPlots` provides plotting for quantum circuits and ZX diagrams. You can use it to visualize your quantum circuits in [`VSCode`](https://code.visualstudio.com/), [`Jupyter`](https://jupyter.org/) notebook or [`Pluto`](https://github.com/fonsp/Pluto.jl) notebook. ```@example quick-start using Yao.EasyBuild, Yao.YaoPlots @@ -88,4 +93,6 @@ using Compose # show a qft circuit vizcircuit(qft_circuit(5)) -``` \ No newline at end of file +``` + +More details about the plotting can be found in the manual: [Quantum Circuit Visualization](@ref). \ No newline at end of file diff --git a/lib/YaoArrayRegister/src/density_matrix.jl b/lib/YaoArrayRegister/src/density_matrix.jl index b3b91adf..6e3b02e6 100644 --- a/lib/YaoArrayRegister/src/density_matrix.jl +++ b/lib/YaoArrayRegister/src/density_matrix.jl @@ -106,7 +106,7 @@ end function YaoAPI.purify(r::DensityMatrix{D}; num_env::Int = nactive(r)) where {D} Ne = D ^ num_env Ns = size(r.state, 1) - R, U = eigen!(r.state) + R, U = eigen(r.state) state = view(U, :, Ns-Ne+1:Ns) .* sqrt.(abs.(view(R, Ns-Ne+1:Ns)')) return ArrayReg{D}(state) end