GTorlai / PastaQ.jl

Package for Simulation, Tomography and Analysis of Quantum Computers
Apache License 2.0
141 stars 23 forks source link

'ArgumentError: reducing over an empty collection is not allowed' for noisy circuit #291

Closed wzy7178 closed 1 year ago

wzy7178 commented 2 years ago

Dear PastaQ developer(s): Today I tried to use PastaQ to do a noisy VQE, and first checked if the noisy circuit function works on my computer. However, when running the noisy circuit example you provide in the readme.md file, I find the following error (see the log below).

This error appears on my Mac (native M1 Julia build) and an Linux cluster. And the same error occurs when I run the testsets in the test_noise.jl .

Hope to learn about what causes this, thanks!

julia> # define a noise model with different error rates for
       # one- and two-qubit gates
       noisemodel = (1 => ("depolarizing", (p = 0.01,)),
                     2 => ("depolarizing", (p = 0.05,)))
(1 => ("depolarizing", (p = 0.01,)), 2 => ("depolarizing", (p = 0.05,)))

julia> # run a noisy circuit
       ρ = runcircuit(hilbert, circuit; noise = noisemodel)
ERROR: ArgumentError: reducing over an empty collection is not allowed
Stacktrace:
  [1] _empty_reduce_error()
    @ Base ./reduce.jl:301
  [2] reduce_empty(op::Function, #unused#::Type{Union{}})
    @ Base ./reduce.jl:311
  [3] reduce_empty(op::Base.BottomRF{typeof(max)}, #unused#::Type{Union{}})
    @ Base ./reduce.jl:330
  [4] reduce_empty_iter
    @ ./reduce.jl:357 [inlined]
  [5] reduce_empty_iter
    @ ./reduce.jl:356 [inlined]
  [6] foldl_impl(op::Base.BottomRF{typeof(max)}, nt::Base._InitialValue, itr::Tuple{})
    @ Base ./reduce.jl:49
  [7] mapfoldl_impl(f::typeof(identity), op::typeof(max), nt::Base._InitialValue, itr::Tuple{})
    @ Base ./reduce.jl:44
  [8] mapfoldl(f::Function, op::Function, itr::Tuple{}; init::Base._InitialValue)
    @ Base ./reduce.jl:162
  [9] mapfoldl
    @ ./reduce.jl:162 [inlined]
 [10] #mapreduce#248
    @ ./reduce.jl:289 [inlined]
 [11] mapreduce(f::Function, op::Function, itr::Tuple{})
    @ Base ./reduce.jl:289
 [12] maximum(a::Tuple{}; kw::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ Base ./reduce.jl:737
 [13] maximum(a::Tuple{})
    @ Base ./reduce.jl:737
 [14] nqubits(gate::Tuple{String, Int64})
    @ PastaQ ~/.julia/packages/PastaQ/Kpjqo/src/circuits/circuits.jl:4
 [15] (::PastaQ.var"#106#107")(gate::Tuple{String, Int64})
    @ PastaQ ./none:0
 [16] MappingRF
    @ ./reduce.jl:95 [inlined]
 [17] _foldl_impl(op::Base.MappingRF{PastaQ.var"#106#107", Base.BottomRF{typeof(max)}}, init::Base._InitialValue, itr::Vector{Tuple})
    @ Base ./reduce.jl:58
 [18] foldl_impl
    @ ./reduce.jl:48 [inlined]
 [19] mapfoldl_impl(f::typeof(identity), op::typeof(max), nt::Base._InitialValue, itr::Base.Generator{Vector{Tuple}, PastaQ.var"#106#107"})
    @ Base ./reduce.jl:44
 [20] mapfoldl(f::Function, op::Function, itr::Base.Generator{Vector{Tuple}, PastaQ.var"#106#107"}; init::Base._InitialValue)
    @ Base ./reduce.jl:162
 [21] mapfoldl
    @ ./reduce.jl:162 [inlined]
 [22] mapreduce(f::Function, op::Function, itr::Base.Generator{Vector{Tuple}, PastaQ.var"#106#107"}; kw::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ Base ./reduce.jl:289
 [23] mapreduce
    @ ./reduce.jl:289 [inlined]
 [24] maximum(a::Base.Generator{Vector{Tuple}, PastaQ.var"#106#107"}; kw::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ Base ./reduce.jl:737
 [25] maximum
    @ ./reduce.jl:737 [inlined]
 [26] nqubits
    @ ~/.julia/packages/PastaQ/Kpjqo/src/circuits/circuits.jl:6 [inlined]
 [27] #106
    @ ./none:0 [inlined]
 [28] MappingRF
    @ ./reduce.jl:95 [inlined]
 [29] _foldl_impl(op::Base.MappingRF{PastaQ.var"#106#107", Base.BottomRF{typeof(max)}}, init::Base._InitialValue, itr::Vector{Vector{Tuple}})
    @ Base ./reduce.jl:58
 [30] foldl_impl(op::Base.MappingRF{PastaQ.var"#106#107", Base.BottomRF{typeof(max)}}, nt::Base._InitialValue, itr::Vector{Vector{Tuple}})
    @ Base ./reduce.jl:48
 [31] mapfoldl_impl(f::typeof(identity), op::typeof(max), nt::Base._InitialValue, itr::Base.Generator{Vector{Vector{Tuple}}, PastaQ.var"#106#107"})
    @ Base ./reduce.jl:44
 [32] mapfoldl(f::Function, op::Function, itr::Base.Generator{Vector{Vector{Tuple}}, PastaQ.var"#106#107"}; init::Base._InitialValue)
    @ Base ./reduce.jl:162
 [33] mapfoldl
    @ ./reduce.jl:162 [inlined]
 [34] mapreduce(f::Function, op::Function, itr::Base.Generator{Vector{Vector{Tuple}}, PastaQ.var"#106#107"}; kw::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ Base ./reduce.jl:289
 [35] mapreduce
    @ ./reduce.jl:289 [inlined]
 [36] maximum(a::Base.Generator{Vector{Vector{Tuple}}, PastaQ.var"#106#107"}; kw::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ Base ./reduce.jl:737
 [37] maximum(a::Base.Generator{Vector{Vector{Tuple}}, PastaQ.var"#106#107"})
    @ Base ./reduce.jl:737
 [38] nqubits
    @ ~/.julia/packages/PastaQ/Kpjqo/src/circuits/circuits.jl:6 [inlined]
 [39] insertnoise(circuit::Vector{Vector{Tuple}}, noisemodel::Tuple{Pair{Int64, Tuple{String, NamedTuple{(:p,), Tuple{Float64}}}}, Pair{Int64, Tuple{String, NamedTuple{(:p,), Tuple{Float64}}}}}; gate::Nothing)
    @ PastaQ ~/.julia/packages/PastaQ/Kpjqo/src/circuits/noise.jl:143
 [40] insertnoise
    @ ~/.julia/packages/PastaQ/Kpjqo/src/circuits/noise.jl:142 [inlined]
 [41] #insertnoise#96
    @ ~/.julia/packages/PastaQ/Kpjqo/src/circuits/noise.jl:199 [inlined]
 [42] insertnoise
    @ ~/.julia/packages/PastaQ/Kpjqo/src/circuits/noise.jl:199 [inlined]
 [43] buildcircuit(hilbert::Vector{Index{Int64}}, circuit::Vector{Tuple}; noise::Tuple{Pair{Int64, Tuple{String, NamedTuple{(:p,), Tuple{Float64}}}}, Pair{Int64, Tuple{String, NamedTuple{(:p,), Tuple{Float64}}}}}, eltype::Nothing, device::typeof(identity))
    @ PastaQ ~/.julia/packages/PastaQ/Kpjqo/src/circuits/runcircuit.jl:24
 [44] runcircuit(hilbert::Vector{Index{Int64}}, circuit::Vector{Tuple}; full_representation::Bool, process::Bool, noise::Tuple{Pair{Int64, Tuple{String, NamedTuple{(:p,), Tuple{Float64}}}}, Pair{Int64, Tuple{String, NamedTuple{(:p,), Tuple{Float64}}}}}, eltype::Nothing, device::Function, kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ PastaQ ~/.julia/packages/PastaQ/Kpjqo/src/circuits/runcircuit.jl:127
 [45] top-level scope
    @ REPL[10]:2
wzy7178 commented 2 years ago

I also find the noiseless VQE code shown in the readme.md is not fully working on my laptop, and Julia say the function rayleigh_quotient is not defined. I have to find the function on GitHub and put it into my program. Moreover, in the current version on the GitHub, it is defined as

function rayleigh_quotient(O::MPO, U::Vector{ITensor}, ψ::MPS; kwargs...) Uψ = runcircuit(ψ, U; kwargs...) return real(ITensors.inner(Uψ, O, Uψ)) end which is not compatible with the newest ITensor version. After I replace it with return real(ITensors.inner((Uψ)', O, Uψ)) if finally worked.

wzy7178 commented 2 years ago

I think the error is caused by the function nqubits, defined as the following: nqubits(gate::Tuple) = maximum(Ops.sites(Op(gate)))

Ops.sites will return ( ) when given a circuit defined in the example in readme.md.

mtfishman commented 2 years ago

Thanks for the report, this is actually broken even in the most minimal example of runcircuit:

runcircuit([("X", 1)])

This was broken by a big internal change we made to the operator algebra system in ITensors.jl: https://github.com/ITensor/ITensors.jl/pull/920 which we was include in ITensors 0.3.14. Unfortunately some of behavior changed which we were using in PastaQ and broke the functionality for parsing the gate list, as you identified.

I made a patch here: https://github.com/GTorlai/PastaQ.jl/pull/292 which will be included in the next PastaQ release (PastaQ 0.0.24).

wzy7178 commented 2 years ago

Many thanks!

mtfishman commented 2 years ago

Ok it should be fixed in PastaQ 0.0.24, please let me know if it works and I'll close this issue.