Getting Started


“Whatever you say, sir. Thy will be done.”—Montgomery Scott


Scotty is a quantum computing framework for Scala developers. It comes with a quantum computer simulator that can be used for writing hybrid programs out-of-the-box.

Most quantum frameworks and simulators are written either in quantum-specific languages (like Q# and QISKit) or Python. Scotty is one of the first attempts at building a cross-platform quantum framework on top of the JVM.

It was built with three principles in mind:

  • Write once, run anywhere: experiment with quantum code and run it with Scotty. Export Scotty circuits (coming soon) to Quil or OpenQASM and run it on other simulators or real quantum computers.
  • Expandability: provide a high-level set of abstractions that can be expanded on different architectures.
  • No PhD required: it should be easy to get started and everything should work intuitively out-of-the-box.

Installation

If you’re using SBT, add the following line to your build file:

libraryDependencies += "xyz.entangled" %% "scotty" % "0.6.0"

For Maven and other build tools, check out Maven Search.

Scotty supports Scala 2.12 and 2.13.

You need to know basic quantum computing and Scala concepts before digging into Scotty. At some point we are going to publish an intro level tutorial for software engineers that covers the basics of quantum programming in the context of classical software to help with onboarding.

After you add Scotty to your project you can start writing code—there are no other extensions or libraries that you have to install.

Basic Tutorial

Let’s build a simple quantum circuit that entangles two qubits. Such a circuit contains two quantum gates and it produces a so-called Bell pair:

Circuit(H(0), CNOT(0, 1))

Scotty analyzes qubit indexes referenced in the circuit definition and then instantiates the circuit with a matching register of qubits in the default state of $\lvert0\rangle$. Use the withRegister method to initialize a circuit with a custom qubit register:

Circuit(H(0), CNOT(0, 1)).withRegister("10")

Scotty uses a little-endian order for register initialization and state readouts. In our example, qubit 0 is the first qubit in the 10 register and it can be located at index 0.

Often it’s useful to abstract qubit indexes into variables by introducing a function:

def entangle(q1: Int, q2: Int) = Circuit(H(q1), CNOT(q1, q2))

Now that we have a quantum circuit let’s try to run it. Scotty features a Scala trait called QuantumContext that provides useful method signatures for quantum state and gate operations. QuantumSimulator implements the trait and lets us run small quantum circuits in a simulated environment:

QuantumSimulator().run(entangle(0, 1))

If the circuit contains measurement operations it returns a Collapsed state. In our case, since there are no measurements yet, the simulator returns a Superposition. This case class is a wrapper around a state vector and it comes with several useful methods. For convenience, Scotty provides a special superposition wrapper trait called StateReader. One implementation called QubitProbabilityReader shows one-qubit state probabilities for the current superposition state:

QubitProbabilityReader(QuantumSimulator().run(entangle(0, 1))).toHumanString

The result of this readout is:

qubit_0: P(0) = 50.0% P(1) = 50.0%
qubit_1: P(0) = 50.0% P(1) = 50.0%

This is exactly what we would expect for both states of two entangled qubits.

Another way to look at the superposition is with the StateProbabilityReader. Instead of showing probabilities of single qubits, it shows amplitudes and probabilities for all register states. In our case it’s a two-qubit state since we only have two qubits that we are working with.

00: Amplitude: 0.707+0.000i, P: 50.00%
11: Amplitude: 0.707+0.000i, P: 50.00%

Again, as expected we get 50% probability for $\lvert00\rangle$ and $\lvert11\rangle$ states.

Finally, to measure a circuit we can either add a Measure operation to the circuit or use QuantumSimulator().runAndMeasure:

QuantumSimulator().runAndMeasure(entangle(0, 1)).toHumanString

This code returns either

bit_0: 1
bit_1: 1

or

bit_0: 0
bit_1: 0

Now, that you have a better idea of how Scotty works take a look at other topics starting with QuantumContext.