Skip to content

Commit

Permalink
Add Data Tools (#11)
Browse files Browse the repository at this point in the history
* minor fixes to docs and code comments
* add spin2int, int2spin, spin2binary, closes #6
* add limit and sort features to print_z_state_probabilities
* add note to changelog

Co-authored-by: zmorrell <zmorrell7@gmail.com>
  • Loading branch information
ccoffrin and zmorrell committed Feb 12, 2022
1 parent 0af5f9c commit bfad91f
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 17 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ QuantumAnnealing.jl Change Log
==============================

### Staged
- nothing
- Add data processing tools (#6)

### v0.0.1
- Initial release
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Increase the annealing time to approach the adiabatic limit,
print_z_state_probabilities(ρ)
```

Change the annealing schedule and observer different state probabilities,
Change the annealing schedule and observe different state probabilities,
```
ρ = simulate(ising_model, 10.0, AS_QUADRATIC)
print_z_state_probabilities(ρ)
Expand Down
48 changes: 43 additions & 5 deletions src/base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ converts a integer id into a binary state vector following the package conventio
valid ints are from 0-to-2^n-1
pad should be the total number qubits in the system
"""
function int2binary(x; pad=0)
function int2binary(x::Int; pad=0)
return digits(x, base=2, pad=pad)
end

Expand All @@ -87,6 +87,30 @@ function binary2spin(states::Vector)
return [v == 0 ? 1 : -1 for v in states]
end

"""
converts a spin state vector into an integer id following the package conventions
valid ints are from 0-to-2^n-1
"""
function spin2int(spin::Vector)
return binary2int(spin2binary(spin))
end

"""
converts a integer id into a spin state vector following the package conventions
valid ints are from 0-to-2^n-1
pad should be the total number qubits in the system
"""
function int2spin(x::Int; pad=0)
return binary2spin(int2binary(x, pad=pad))
end

"""
converts a spin state vector (-1/1) into an binary state vector (0/1)
"""
function spin2binary(spin::Vector)
return [i == 1 ? 0 : 1 for i in spin]
end


"""
converts a binary state vector into a bra-ket notation string
Expand Down Expand Up @@ -116,15 +140,29 @@ end

"""
given a 2^n vector of probably values, prints each value and its associated
state vector.
state vector. `limit` is used to limit the total number of states that are
printed. `sort` is used to re-order the states by most likely instead of the
default which is numerical order from 0-to-(2^n-1)
"""
function print_z_state_probabilities(density::Matrix)
function print_z_state_probabilities(density::Matrix; limit=50, sort=false)
probs = z_measure_probabilities(density)
n = ceil(Int, log2(length(probs)))
for (i,pr) in enumerate(probs)
state = binary2spin(int2binary(i-1, pad=n))

prob_order = enumerate(probs)
if sort
prob_order = Base.sort(collect(prob_order), by=(x) -> x[2], rev=true)
end

i = 0
for (state_id,pr) in prob_order
state = int2spin(state_id-1, pad=n)
state_string = spin2braket(state)
prob_string = rpad(round(pr, digits=6),8, " ")
println("$(prob_string) $(state_string)")
i += 1
if limit > 0 && i >= limit
println("first $(limit) of $(length(probs)) states shown")
break
end
end
end
7 changes: 4 additions & 3 deletions src/dwave.jl
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ function _calc_linear_pwp(x_values, y_values)
end


# construct a spline based piecewise quadratic function
# construct a spline-based piecewise quadratic function
function _calc_quadratic_pwp(x_values, y_values)
@assert(length(x_values) == length(y_values))

Expand Down Expand Up @@ -154,7 +154,7 @@ function parse_dwave_annealing_schedule(infile; header=1, delim=',', interpolati
push!(b_values, row[3])
end

# rescale based on D-Wave hamiltonian convention
# rescale and swap sign based on D-Wave hamiltonian convention
# https://docs.dwavesys.com/docs/latest/c_qpu_annealing.html
a_values = a_values ./ -2.0
b_values = b_values ./ 2.0
Expand Down Expand Up @@ -302,7 +302,7 @@ function write_dwisc(outfile::String, ρ, ising_model, qubit_ids; simulated_num_

for state_int in 0:(2^n-1)
prob = probs[state_int+1]
spin_vector = binary2spin(int2binary(state_int, pad=n))
spin_vector = int2spin(state_int, pad=n)
energy = _eval_state_energy(spin_vector, ising_model)

sol_data = Dict(
Expand Down Expand Up @@ -341,6 +341,7 @@ function dwave_annealing_protocol(annealing_schedule::AnnealingSchedule; asch=[(
s1,s_eff_1 = asch[i+1]
asch_slopes[i] = (s_eff_1 - s_eff_0)/(s1 - s0)
end

#branchless piecewise function using linear interpolation from y = m*(x-x0) + y0
function asch_func(s)
return sum([(asch_slopes[i]*(s-asch[i][1]) + asch[i][2]) * (asch[i][1] <= s < asch[i+1][1]) for i = 1:(length(asch)-1)]) + ((s == asch[end][1])*asch[end][2])
Expand Down
1 change: 0 additions & 1 deletion src/simulate.jl
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,6 @@ function simulate(ising_model::Dict, annealing_time::Real, annealing_schedule::A
Ω2Const = integ2A * constant_bracket_x + integ2B * constant_bracket_z
Ω2 = (Ω2Sched + Ω2Const)/2

#display(Ω2)
U_next = exp(Matrix(-im * (annealing_time*Ω1 + (annealing_time^2)*Ω2)))
U = U_next * U

Expand Down
40 changes: 35 additions & 5 deletions test/base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
@testset "state encoding and transformation" begin

@testset "int2binary" begin
@test int2binary(0) == []
@test int2binary(1) == [1]
@test int2binary(2) == [0,1]

@test int2binary(0, pad=3) == [0, 0, 0]
@test int2binary(1, pad=3) == [1, 0, 0]
@test int2binary(2, pad=3) == [0, 1, 0]
Expand All @@ -10,19 +14,45 @@
@test int2binary(4, pad=4) == [0, 0, 1, 0]
end

@testset "binary2int" begin
@testset "int2spin" begin
@test int2spin(0) == []
@test int2spin(1) == [-1]
@test int2spin(2) == [1,-1]

@test int2spin(0, pad=3) == [ 1, 1, 1]
@test int2spin(1, pad=3) == [-1, 1, 1]
@test int2spin(2, pad=3) == [ 1, -1, 1]
@test int2spin(4, pad=3) == [ 1, 1, -1]

@test int2spin(4, pad=4) == [1, 1, -1, 1]
end

@testset "int2binary/binary2int" begin
for i in 0:16
@test binary2int(int2binary(i, pad=10)) == i
end
end

@testset "int2spin/spin2int" begin
for i in 0:16
@test spin2int(int2spin(i, pad=10)) == i
end
end

@testset "binary2spin" begin
@test binary2spin([0, 0, 0]) == [ 1, 1, 1]
@test binary2spin([1, 0, 0]) == [-1, 1, 1]
@test binary2spin([0, 1, 0]) == [ 1, -1, 1]
@test binary2spin([0, 0, 1]) == [ 1, 1, -1]
end

@testset "spin2binary" begin
@test spin2binary([ 1, 1, 1]) == [0, 0, 0]
@test spin2binary([-1, 1, 1]) == [1, 0, 0]
@test spin2binary([ 1, -1, 1]) == [0, 1, 0]
@test spin2binary([ 1, 1, -1]) == [0, 0, 1]
end

@testset "binary2braket" begin
@test binary2braket(int2binary(0, pad=3)) == "|000⟩"
@test binary2braket(int2binary(1, pad=3)) == "|001⟩"
Expand All @@ -31,10 +61,10 @@
end

@testset "binary2braket" begin
@test spin2braket(binary2spin(int2binary(0, pad=3))) == "|↑↑↑⟩"
@test spin2braket(binary2spin(int2binary(1, pad=3))) == "|↑↑↓⟩"
@test spin2braket(binary2spin(int2binary(2, pad=3))) == "|↑↓↑⟩"
@test spin2braket(binary2spin(int2binary(4, pad=3))) == "|↓↑↑⟩"
@test spin2braket(int2spin(0, pad=3)) == "|↑↑↑⟩"
@test spin2braket(int2spin(1, pad=3)) == "|↑↑↓⟩"
@test spin2braket(int2spin(2, pad=3)) == "|↑↓↑⟩"
@test spin2braket(int2spin(4, pad=3)) == "|↓↑↑⟩"
end

end
Expand Down
2 changes: 1 addition & 1 deletion test/data/generate_schedule_csvs.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using DelimitedFiles

# add a factor of 2x based on D-Wave hamiltonian convention
# add a factor of 2x and sign inversion based on D-Wave Hamiltonian convention
# https://docs.dwavesys.com/docs/latest/c_qpu_annealing.html
A = (s) -> -2.0*cos/2*s)
B = (s) -> 2.0*sin/2*s)
Expand Down

0 comments on commit bfad91f

Please sign in to comment.