1- # Quantum SVD
2- # Reference: https://arxiv.org/abs/1905.01353
3- export QuantumSVD, circuit_qsvd, train_qsvd!, readout_qsvd
1+ using QuAlgorithmZoo, Yao,YaoExtensions
2+ using BitBasis: log2i
3+ using Test
4+ using Random, LinearAlgebra
45
56"""
67Quantum singular value decomposition algorithm.
@@ -14,12 +15,12 @@ Quantum singular value decomposition algorithm.
1415"""
1516function train_qsvd! (reg, circuit_a:: AbstractBlock{Na} , circuit_b:: AbstractBlock{Nb} , optimizer; Nc:: Int = min (Na, Nb), maxiter:: Int = 100 ) where {Na, Nb}
1617 nbit = Na+ Nb
17- c = circuit_qsvd (circuit_a, circuit_b, Nc) |> autodiff ( :QC ) # construct a differentiable circuit for training
18+ c = circuit_qsvd (circuit_a, circuit_b, Nc)
1819
1920 obs = - mapreduce (i-> put (nbit, i=> Z), + , (1 : Na... , Na+ Nc+ 1 : Na+ Nb... ))
2021 params = parameters (c)
2122 for i = 1 : maxiter
22- grad = opdiff .(() -> copy ( reg) | > c, collect_blocks (Diff, c), Ref (obs))
23+ grad = expect ' (obs, reg = > c) . second
2324 QuAlgorithmZoo. update! (params, grad, optimizer)
2425 println (" Iter $i , Loss = $(Na+ expect (obs, copy (reg) |> c)) " )
2526 dispatch! (c, params)
@@ -54,8 +55,8 @@ kwargs includes
5455 * `optimizer`, default is `Adam(lr=0.1)`.
5556"""
5657function QuantumSVD (M:: AbstractMatrix ; Nc:: Int = log2i (min (size (M)... )),
57- circuit_a= variational_circuit (log2i (size (M, 1 )), 5 , pair_ring ( log2i ( size (M, 1 ))) ),
58- circuit_b= variational_circuit (log2i (size (M, 2 )), 5 , pair_ring ( log2i ( size (M, 2 ))) ),
58+ circuit_a= variational_circuit (log2i (size (M, 1 ))),
59+ circuit_b= variational_circuit (log2i (size (M, 2 ))),
5960 maxiter= 200 , optimizer= Adam (lr= 0.1 ))
6061
6162 dispatch! (circuit_a, :random )
@@ -64,3 +65,21 @@ function QuantumSVD(M::AbstractMatrix; Nc::Int=log2i(min(size(M)...)),
6465 train_qsvd! (reg, circuit_a, circuit_b, optimizer, Nc= Nc, maxiter= maxiter)
6566 readout_qsvd (reg, circuit_a, circuit_b, Nc)
6667end
68+
69+ @testset " QSVD" begin
70+ Random. seed! (2 )
71+ # define a matrix of size (2^Na, 2^Nb)
72+ Na = 2
73+ Nb = 2
74+
75+ # the exact result
76+ M = reshape (rand_state (Na+ Nb). state, 1 << Na, 1 << Nb)
77+ U_exact, S_exact, V_exact = svd (M)
78+
79+ U, S, V = QuantumSVD (M; maxiter= 400 )
80+
81+ @test isapprox (U* Diagonal (S)* V' , M, atol= 1e-2 )
82+ @test isapprox (abs .(S), S_exact, atol= 1e-2 )
83+ @test isapprox (U' * U_exact .| > abs2, I, atol= 1e-2 )
84+ @test isapprox (V' * V_exact .| > abs2, I, atol= 1e-2 )
85+ end
0 commit comments