Julia Community 🟣

Katharine Hyatt
Katharine Hyatt

Posted on

Introducing Braket.jl - Quantum Computing with Julia

Braket.jl is a new, experimental package that lets you
build quantum circuits and programs in Julia and run them on Amazon Braket. It's a ground-up rewrite of the Amazon Braket Python SDK allowing Julia users and developers to work with Amazon Braket and quantum computing in their preferred language. The package is Apache-2.0 licensed, and currently supports Julia >=1.6 on x64 Windows, Linux, or OSX.

Amazon Braket is a fully managed AWS service that helps researchers, scientists, and developers get started with quantum computing. Through Amazon Braket, you can develop, run, test, and benchmark quantum algorithms on state-of-the-art quantum hardware and simulators. More information on Amazon Braket can be found in our Developer Guide.

Almost all of the Python SDK's features are reimplemented in Julia — for those few that aren't, we are also providing a subsidiary package, PyBraket.jl, which allows you to translate Julia objects into their Python equivalents and call the Python SDK. For more information about which features are available entirely in Julia, see the Braket.jl README.

We've created this package because we know there are a lot of current and future quantum experts in the Julia community. We want to allow you to experiment and try out this exciting new technology using all the Julia features we know and love — multiple dispatch, native parallelism, a great package management system, and first class performance. We also want to learn from the Julia community, and better understand how we can enable you to do groundbreaking work in the quantum space.

Because this package is an experimental release, we can't promise the same support level as the Python SDK provides. If you run into issues or see that a feature you'd like to use isn't yet implemented, please open an Issue at the GitHub repository. We also welcome community contributions, both bugfixes and new feature implementations.

Some usage examples

Note: all these examples include PyBraket.jl in order to use the Amazon Braket local simulator, which runs on your local computer (e.g., your Jupyter or Pluto notebook, or your laptop). You won't incur any charges from running these examples. If you want to run on an on-demand, AWS-managed device — simulator or QPU — you can do so by creating an AwsDevice object and supply the device ARN. See the Developer Guide for more information about available devices.

Now we can take a look at some "Hello world!" examples, one gate-based, and one in the paradigm of analog Hamiltonian simulation.

Building a Bell state

using Braket, PyBraket

dev = LocalSimulator()
c = Circuit()
c(H, 0) # build up circuits iteratively
c(CNot, 0, 1)
c(Amplitude, ["00", "11"])
local_task = run(dev, c, shots=0)
task_result = result(local_task)
@show task_result[Amplitude(["00", "11"])]
Enter fullscreen mode Exit fullscreen mode

which will return:

task_result[Amplitude(["00", "11"])] = Dict{String, ComplexF64}("00" => 0.7071067811865475 + 0.0im, "11" => 0.7071067811865475 + 0.0im)
Dict{String, ComplexF64} with 2 entries:
  "00" => 0.707107+0.0im
  "11" => 0.707107+0.0im
Enter fullscreen mode Exit fullscreen mode

Running your first analog Hamiltonian simulation

Amazon Braket has just added a new device, QuEra's Aquila. Aquila runs on a computing model fundamentally different from gate-based computation: instead of gates, we program the QPU by specifying a time dependent Hamiltonian. To learn more about this model of quantum computation, see the dev guide. Amazon Braket provides a local (Python) simulator for AHS programs.

Let's write a very simple AHS program to check the Rabi frequency of just one atom:

using Braket, PyBraket
using DataStructures, Braket.DecFP

register = AtomArrangement()
push!(register, AtomArrangementItem((0, 0)))
device = LocalSimulator("braket_ahs") # use the AHS local simulator

Ω_max = Dec128("2.5e6")
trange = range(0, 4π/(Ω_max), 21)[2:end]

function get_counts(result)
    state_counts = Accumulator{String, Int}()
    states = ["e", "r", "g"]
    for shot in result.measurements
        pre       = convert(Vector{Int}, shot.pre_sequence)
        post      = convert(Vector{Int}, shot.post_sequence)
        state_idx = (pre .* (1 .+ post)) .+ 1
        state     = prod([states[s_idx] for s_idx in state_idx])
        inc!(state_counts, state)
    end
    return state_counts
end

function get_program(t_max)
    Ω = TimeSeries()
    Ω[0.0] = Ω_max
    Ω[t_max] = Ω_max

    ϕ = TimeSeries()
    ϕ[0.0] = 0.0
    ϕ[t_max] = 0.0

    Δ = TimeSeries()
    Δ[0.0] = 0.0
    Δ[t_max] = 0.0

    drive = DrivingField(Ω, ϕ, Δ)

    return AnalogHamiltonianSimulation(register, drive)
end

programs = trange .|> get_program
local_results = [result(run(device, program, shots=1000)) for program in programs]
state_counts = local_results .|> get_counts
using Plots

p = plot(trange, [state_count["g"] for state_count in state_counts], marker=:circle)
Enter fullscreen mode Exit fullscreen mode

Which will create a plot such as the below:

RabiFrequency

Run a simulation of a noisy circuit

You can also apply noise to your quantum circuits and investigate how this affects your results. The local simulator supports running density matrix based noise simulations, or you can use the on-demand simulator DM1.

circ  = Circuit([(H, 0), (CNot, 0, 1)])
noise = BitFlip(0.1)
circ  = Braket.apply_gate_noise!(circ, noise)

device = LocalSimulator("braket_dm")
task = run(device, circ, shots=1000)

t_result = result(task)
measurement = t_result.measurement_counts
Enter fullscreen mode Exit fullscreen mode

How to find out more and contribute

Please check out the Braket.jl docs for more information about the package. We strongly recommend taking a look at the Amazon Braket Developer Guide as well to familiarize yourself with the service. We also provide several pure-Julia examples in the examples directory of the repository which you can try out yourself.

We are actively looking for contributors! You don't need to be a quantum expert (yet!) to contribute - we're looking for introductory tutorials, new features, bug reports, and general user experience feedback. Whether you're just getting started in quantum computing or are an advanced developer who wants to build a Julia plugin on top of Amazon Braket, we'd love feedback at the project's Github repo. If you're interested in contributing PRs or reporting bugs, please see our Contributing Guide for more information.

For general usage questions, you can also reach us on Julia slack or Discourse.

Top comments (4)

Collapse
 
janiserdmanis profile image
Jānis Erdmanis

This looks cool and quite accessable!

I wonder if you could comment on the decission on the user API for initating circuits as shown in Bell State example where you add gates with c(H, 0) rather than providing a method likeadd!(H, 0). It's a curios choice.

Collapse
 
kshyatt profile image
Katharine Hyatt

In fact there are multiple ways to add a gate to a circuit. You could also do:

c = Circuit()
c = Braket.add_gate!(c, H, 0)
Enter fullscreen mode Exit fullscreen mode

if that's a syntax you prefer.

Or you can also do:

c = Circuit()
c = H(c, 0)
Enter fullscreen mode Exit fullscreen mode
Collapse
 
abhimanyuaryan profile image
abhimanyuaryan

This is pretty cool. Congrats everyone

Collapse
 
logankilpatrick profile image
Logan Kilpatrick

This is so awesome to see! Congrats Katie and the rest of the AWS Quantum team.