Skip to content

Commit

Permalink
Merge pull request #6 from jgidi/development
Browse files Browse the repository at this point in the history
Use standard gains by default
  • Loading branch information
jgidi authored Sep 22, 2021
2 parents 8271ca5 + c4ac6e9 commit bb78dca
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 27 deletions.
24 changes: 12 additions & 12 deletions src/include/gains.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,20 @@
Contains the gain parameters used for the optimizers defined within the `ComplexSPSA` module.
"""
# gains = Dict(
# :a => 3,
# :b => 0.1,
# :A => 1.0,
# :s => 1.0,
# :t => 1/6,
# )
gains = Dict(
:a => 2pi/10,
:b => 0.2,
:A => 0.0,
:s => 0.602,
:t => 0.101,
:a => 3,
:b => 0.1,
:A => 1.0,
:s => 1.0,
:t => 1/6,
)
# gains = Dict(
# :a => 2pi/10,
# :b => 0.2,
# :A => 0.0,
# :s => 0.602,
# :t => 0.101,
# )

function calibrate_gain_a(f, z, target_a, b, perturbations, Ncalibrate)
avg = 0.0
Expand Down
8 changes: 8 additions & 0 deletions src/include/qiskit/Qiskit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@ module Qiskit

using PyCall

gains = Dict(
:a => 3,
:b => 0.1,
:A => 1.0,
:s => 1.0,
:t => 1/6,
)

include("include/real_optimizers.jl")
include("include/complex_optimizers.jl")
include("include/tools.jl")
Expand Down
39 changes: 30 additions & 9 deletions src/include/qiskit/include/complex_optimizers.jl
Original file line number Diff line number Diff line change
@@ -1,49 +1,68 @@
"""
SPSA_on_complex(f, guess::Vector{Complex{Float64}}, Niters)
SPSA_on_complex(f, guess::Vector{Complex{Float64}}, Niters;
a = Qiskit.gains[:a], b = Qiskit.gains[:b],
A = Qiskit.gains[:A], s = Qiskit.gains[:s], t = Qiskit.gains[:t] )
Wrapper around [`SPSA`](@ref) which internally converts the
complex-valued initial point, `guess`, and objective function, `f`,
to be optimized as a real-variable problem with twice the parameters.
"""
function SPSA_on_complex(f, guess::Vector{Complex{Float64}}, Niters)
function SPSA_on_complex(f, guess::Vector{Complex{Float64}}, Niters;
a = gains[:a], b = gains[:b],
A = gains[:A], s = gains[:s], t = gains[:t],
)
# Prepare real-variable versions of the function f and the initial value
f_real(x) = f(reinterpret(Complex{Float64}, x))
guess_real = reinterpret(Float64, guess)

# Solve using real optimizer
xacc = SPSA(f_real, guess_real, Niters)
xacc = SPSA(f_real, guess_real, Niters,
a = a, b = b, A = A, s = s, t = t,
)

# Return optimized variables as complex
return reinterpret(Complex{Float64}, xacc)
end

"""
SPSA2_on_complex(f, guess::Vector{Complex{Float64}}, Niters)
SPSA2_on_complex(f, guess::Vector{Complex{Float64}}, Niters;
b = Qiskit.gains[:b], A = Qiskit.gains[:A],
s = Qiskit.gains[:s], t = Qiskit.gains[:t] )
Wrapper around [`SPSA2`](@ref) which internally converts the
complex-valued initial point, `guess`, and objective function, `f`,
to be optimized as a real-variable problem with twice the parameters.
"""
function SPSA2_on_complex(f, guess::Vector{Complex{Float64}}, Niters)
function SPSA2_on_complex(f, guess::Vector{Complex{Float64}}, Niters;
b = gains[:b],
A = gains[:A], s = gains[:s], t = gains[:t],
)
# Prepare real-variable versions of the function f and the initial value
f_real(x) = f(reinterpret(Complex{Float64}, x))
guess_real = reinterpret(Float64, guess)

# Solve using real optimizer
xacc = SPSA2(f_real, guess_real, Niters)
xacc = SPSA2(f_real, guess_real, Niters,
b = b, A = A, s = s, t = t,
)

# Return optimized variables as complex
return reinterpret(Complex{Float64}, xacc)
end

"""
SPSA_NG_on_complex(f, fidelity, guess::Vector{Complex{Float64}}, Niters)
SPSA_NG_on_complex(f, fidelity, guess::Vector{Complex{Float64}}, Niters;
b = Qiskit.gains[:b], A = Qiskit.gains[:A],
s = Qiskit.gains[:s], t = Qiskit.gains[:t] )
Wrapper around [`SPSA_NG`](@ref) which internally converts the
complex-valued initial point, `guess`, the `fidelity`, and the objective function, `f`,
to be optimized as a real-variable problem with twice the parameters.
"""
function SPSA_NG_on_complex(f, fidelity, guess::Vector{Complex{Float64}}, Niters)
function SPSA_NG_on_complex(f, fidelity, guess::Vector{Complex{Float64}}, Niters;
b = gains[:b],
A = gains[:A], s = gains[:s], t = gains[:t],
)
# Prepare real-variable versions of the function f,
# the fidelity, and the initial value
f_real(x) = f(reinterpret(Complex{Float64}, x))
Expand All @@ -52,7 +71,9 @@ function SPSA_NG_on_complex(f, fidelity, guess::Vector{Complex{Float64}}, Niters
reinterpret(Complex{Float64}, y))

# Solve using real optimizer
xacc = SPSA_NG(f_real, fid_real, guess_real, Niters)
xacc = SPSA_NG(f_real, fid_real, guess_real, Niters,
b = b, A = A, s = s, t = t,
)

# Return optimized variables as complex
return reinterpret(Complex{Float64}, xacc)
Expand Down
45 changes: 39 additions & 6 deletions src/include/qiskit/include/real_optimizers.jl
Original file line number Diff line number Diff line change
@@ -1,19 +1,30 @@
"""
SPSA(f, guess, Niters)
SPSA(f, guess, Niters;
a = Qiskit.gains[:a], b = Qiskit.gains[:b],
A = Qiskit.gains[:A], s = Qiskit.gains[:s], t = Qiskit.gains[:t] )
Wrapper around the first order [SPSA optimizer from Qiskit](https://qiskit.org/documentation/stubs/qiskit.algorithms.optimizers.QNSPSA.html#qiskit.algorithms.optimizers.SPSA).
"""
function SPSA(f, guess, Niters)
function SPSA(f, guess, Niters;
a = gains[:a], b = gains[:b],
A = gains[:A], s = gains[:s], t = gains[:t],
)
# Select optimizer class from python library
qiskit_opts = pyimport("qiskit.algorithms.optimizers")

# Preallocate array to store optimized variables
Nx = length(guess)
values = Array{Float64}(undef, Nx, Niters)

# Gain parameters
ak = [ a / (k + A)^s for k in 1:Niters ]
bk = [ b / (k)^t for k in 1:Niters ]

# Define optimizer rules
optimizer = qiskit_opts.SPSA(maxiter = Niters,
callback = callback_accumulator(values),
learning_rate = ak,
perturbation = bk,
)

# Start optimization
Expand All @@ -25,22 +36,33 @@ function SPSA(f, guess, Niters)
end

"""
SPSA2(f, guess, Niters)
SPSA2(f, guess, Niters;
b = Qiskit.gains[:b], A = Qiskit.gains[:A],
s = Qiskit.gains[:s], t = Qiskit.gains[:t] )
Wrapper around the second order [SPSA optimizer from Qiskit](https://qiskit.org/documentation/stubs/qiskit.algorithms.optimizers.QNSPSA.html#qiskit.algorithms.optimizers.SPSA).
"""
function SPSA2(f, guess, Niters)
function SPSA2(f, guess, Niters;
b = gains[:b],
A = gains[:A], s = gains[:s], t = gains[:t],
)
# Select optimizer class from python library
qiskit_opts = pyimport("qiskit.algorithms.optimizers")

# Preallocate array to store optimized variables
Nx = length(guess)
values = Array{Float64}(undef, Nx, Niters)

# Gain parameters
ak = [ 1 / (k + A)^s for k in 1:Niters ]
bk = [ b / (k)^t for k in 1:Niters ]

# Define optimizer rules
optimizer = qiskit_opts.SPSA(maxiter = Niters,
callback = callback_accumulator(values),
second_order = true,
learning_rate = ak,
perturbation = bk,
)

# Start optimization
Expand All @@ -52,22 +74,33 @@ function SPSA2(f, guess, Niters)
end

"""
SPSA_NG(f, fidelity, guess, Niters)
SPSA_NG(f, fidelity, guess, Niters;
b = Qiskit.gains[:b], A = Qiskit.gains[:A],
s = Qiskit.gains[:s], t = Qiskit.gains[:t] )
Wrapper around the [QNSPSA optimizer from Qiskit](https://qiskit.org/documentation/stubs/qiskit.algorithms.optimizers.QNSPSA.html#qiskit.algorithms.optimizers.QNSPSA).
"""
function SPSA_NG(f, fidelity, guess, Niters)
function SPSA_NG(f, fidelity, guess, Niters;
b = gains[:b],
A = gains[:A], s = gains[:s], t = gains[:t],
)
# Select optimizer class from python library
qiskit_opts = pyimport("qiskit.algorithms.optimizers")

# Preallocate array to store optimized variables
Nx = length(guess)
values = Array{Float64}(undef, Nx, Niters)

# Gain parameters
ak = [ 1 / (k + A)^s for k in 1:Niters ]
bk = [ b / (k)^t for k in 1:Niters ]

# Define optimizer rules
optimizer = qiskit_opts.QNSPSA(maxiter = Niters,
fidelity = fidelity,
callback = callback_accumulator(values),
learning_rate = ak,
perturbation = bk,
)

# Start optimization
Expand Down

0 comments on commit bb78dca

Please sign in to comment.