Introduction
Interested in learning how to program quantum computers? Then check out our Qiskit textbook Introduction to Quantum Computing with Qiskit.
This tutorial is the first tutorial in the series on Photonic Quantum Computing with the Perceval API from Quandela. In this tutorial we will look how to install Perceval and then how to implement a simple optical circuit that uses a beam splitter to put qubits in to superposition.
What is Perceval?
Perceval is an open source framework developed by Quandela that allows users to compose and simulate photonic circuits. It allows users to implement a number of optical components from Beam splitters which we will be using in this tutorial to Polarizers, Phase Shifters, and single photon sources.
For more on Perceval go to the website here: https://perceval.quandela.net/
Installing Perceval
The Perceval API can be installed easily from pip. Simple go in to your terminal and type in:
pip install perceval-quandela
Implementing a Beam Splitter
Now that we have installed Perceval we can now create our first photonic quantum computing circuit! In this tutorial we will start simply by creating a 2 mode optical circuit that implements a beam splitter.
The beam splitter couples two spatial modes together. It can be defined using the following unitary matrix:
Where Θ corresponds to reflectivity of the beam splitter and Φ the relative phase between the two modes. Using matrix multiplication we can see how these parameters can affect the qubit states.
For our first example lets set the qubit state to |0〉and set the beam splitters parameters such that Θ = 0 and Φ = 0.
Remembering that the column vector associated with |0〉is:
Now we just need to multiply the matrix for the beam splitter with the column vector for |0〉:
Which has left the state unchanged.
If we instead set Θ = π/4 and Φ = 0:
Given that the the probability of a state occurring is the square of the state amplitude:
Probability of |0〉= 0.70710678118^2 = 0.5 or 50%
Probability of |1〉= 0.70710678118^2 = 0.5 or 50%
This shows that if we set Θ = π/4 and Φ = 0 we will have an equal superposition of states! This is also known as a 50:50 beam splitter.
Now that we have gone through how the beam splitter works we can now implement it using the Perceval API.
Step 1: Import the necessary modules
The first step in the code is to import the following modules:
perceval: This is the main Perceval module
perceval.lib.phys: The phys library contains all the components necessary to build the circuit
sympy: A library used for symbolic mathematics
This is done with the following code:
import perceval as pcvl import perceval.lib.phys as phys import sympy as sp
Step 2: Build the Circuit
The next step is to build the circuit:
circuit = phys.Circuit(2) circuit.add((0, 1), phys.BS(theta=sp.pi/4, phi_b=0))
phys.circuit(2) creates a circuit with 2 denoting the number of modes
circuit.add((0, 1), phys.BS(theta=sp.pi/4, phib=0)) adds a beam splitter to modes 0 and 1. Θ is set to π/4 and Φ (denoted as phi_b) is set to 0.
Step 3: Initialise the Backend
The next step is to pick the backend and pass the circuit to it:
simulator_backend = pcvl.BackendFactory().get_backend("Naive") simulator = simulator_backend(circuit.U)
The first line picks the ‘Naive’ backend. There is a comparison table of the different backends in the documentation here: https://perceval.quandela.net/docs/backends.html
The second line passes the unitary matrix associated with the circuit to the backend.
Step 4: Use the Circuit Analyser to get the probability distribution
The final step is to use the circuit analyser to get the probability distribution of each output state. This is done with the following code:
ca = pcvl.CircuitAnalyser(simulator,[pcvl.BasicState([0, 1]), pcvl.BasicState([1, 0])]) pcvl.pdisplay(ca)
The first line passes the simulator and states to the Circuit analyser while the second line displays the probability distribution. The full code to implement the circuit as well as the output is below.
Code
import perceval as pcvl import perceval.lib.phys as phys import sympy as sp circuit = phys.Circuit(2) circuit.add((0, 1), phys.BS(theta=sp.pi/4, phi_b=0)) simulator_backend = pcvl.BackendFactory().get_backend("Naive") simulator = simulator_backend(circuit.U) ca = pcvl.CircuitAnalyser(simulator,[pcvl.BasicState([0, 1]), pcvl.BasicState([1, 0])]) pcvl.pdisplay(ca)