Skip to content

Qadence

Qadence is a Python package that provides a simple interface to build digital-analog quantum programs with tunable qubit interaction defined on arbitrary register topologies realizable on neutral atom devices.

Feature highlights

  • A block-based system for composing complex digital-analog programs in a flexible and scalable manner, inspired by the Julia quantum SDK Yao.jl and functional programming concepts.

  • A simple interface to work with interacting neutral-atom qubit systems using arbitrary registers topologies.

  • An intuitive expression-based system developed on top of the symbolic library Sympy to construct parametric quantum programs easily.

  • High-order generalized parameter shift rules for differentiating parametrized quantum operations.

  • Out-of-the-box automatic differentiability of quantum programs with PyTorch integration.

  • Efficient execution on a variety of different purpose backends: from state vector simulators to tensor network emulators and real devices.

In following are some examples of Qadence possibilites in the analog, digital-analog and digital paradigms.

Analog emulation of a perfect state transfer

This next example showcases the construction and sampling of a system that admits a perfect state transfer between the two edge qubits of a three qubit register laid out in a line. This relies on time-evolving a Hamiltonian for a custom defined qubit interaction until \(t=\frac{\pi}{\sqrt 2}\).

from torch import pi
from qadence import X, Y, HamEvo, Register, product_state, sample, add

# Define the qubit-qubit interaction term.
def interaction(i, j):
    return 0.5 * (X(i) @ X(j) + Y(i) @ Y(j))  # Compose gates in parallel and sum their contribution.

# Initial state with left-most qubit in the 1 state.
init_state = product_state("100")

# Define a register of 3 qubits laid out in a line.
register = Register.line(n_qubits=3)

# Define an interaction Hamiltonian by summing interactions on indexed qubits.
# hamiltonian = interaction(0, 1) + interaction(1, 2)
hamiltonian = add(interaction(*edge) for edge in register.edges)

# Define and time-evolve the Hamiltonian until t=pi/sqrt(2).
t = pi/(2**0.5)  # Dimensionless.
evolution = HamEvo(hamiltonian, t)

# Sample with 100 shots.
samples = sample(register, evolution, state=init_state, n_shots=100)
samples = [Counter({'001': 100})]

Digital-analog example

This final example deals with the construction and sampling of an Ising Hamiltonian that includes a distance-based interaction between qubits and a global analog block of rotations around the \(X\)-axis. Here, global has to be understood as applied to the whole register for qubits.

from torch import pi
from qadence import Register, AnalogRX, sample

# Global analog RX block.
block = AnalogRX(pi)

# Almost non-interacting qubits as too far apart.
register = Register.from_coordinates([(0,0), (0,15)])  # Dimensionless.
samples = sample(register, block)

# Interacting qubits are close to each other.
register = Register.from_coordinates([(0,0), (0,5)])
samples = sample(register, AnalogRX(pi))
distance = 15: samples = [Counter({'11': 100})]
distance =  5: samples = [Counter({'00': 43, '10': 31, '01': 25, '11': 1})]

Sampling the canonical Bell state

This example illustrates how to prepare a Bell state using digital gates and sampling from the outcome bitstring distribution:

from qadence import CNOT, H, chain, sample

# Preparing a Bell state by composing a Hadamard and CNOT gates in sequence.
bell_state = chain(H(0), CNOT(0,1))

# Sample with 100 shots.
samples = sample(bell_state, n_shots=100)
samples = [Counter({'00': 53, '11': 47})]

Further resources

For a more comprehensive introduction and advanced topics, please have a look at the following tutorials:

Installation guide

Qadence can be installed from PyPI with pip as follows:

pip install qadence

The default backend for Qadence is PyQTorch, a differentiable state vector simulator for digital-analog simulation. It is possible to install additional backends and the circuit visualization library using the following extras:

  • braket: the Braket backend.
  • pulser: the Pulser backend for composing, simulating and executing pulse sequences for neutral-atom quantum devices.
  • visualization: to display diagrammatically quantum circuits.

To just get qadence with the pyqtorch backend, simply run:

pip install qadence

To install other backends or the visualization tool, please use:

pip install "qadence[braket,pulser,visualization]"

Warning

In order to correctly install the visualization extra, the graphviz package needs to be installed in your system:

# on Ubuntu
sudo apt install graphviz

# on MacOS
brew install graphviz

# via conda
conda install python-graphviz

Install from source

We recommend to use the hatch environment manager to install qadence from source:

python -m pip install hatch

# get into a shell with all the dependencies
python -m hatch shell

# run a command within the virtual environment with all the dependencies
python -m hatch run python my_script.py

Warning

hatch will not combine nicely with other environment managers such Conda. If you want to use Conda, install it from source using pip:

# within the Conda environment
python -m pip install -e .

Citation

If you use Qadence for a publication, we kindly ask you to cite our work using the following BibTex entry:

@misc{qadence2023pasqal,
  url = {https://github.com/pasqal-io/qadence},
  title = {Qadence: {A} {D}igital-analog quantum programming interface.},
  year = {2023}
}