Getting started


SimulaQron requires Python 3 and Twisted along with the packages numpy, scipy, Cython, service_identity, matplotlib, networkx, bitstring, black, flake8, click and daemons.


To install SimulaQron itself, you can clone the git repository. Do:

git clone

You will then need to set the following environment variable in order to execute the code. Assuming that you use bash (e.g., standard on OSX or the GIT Bash install on Windows 10), otherwise set the same variables using your favorite shell.:

export PYTHONPATH=yourPath/SimulaQron:$PYTHONPATH

where yourPath is the directory containing SimulaQron. You can add this to your ~/.bashrc or ~/.bash_profile file.

Verifying the installation

To run SimulaQron you need to following Python packages:

  • numpy
  • scipy
  • Cython
  • service_identity
  • twisted
  • matplotlib
  • networkx
  • bitstring
  • black
  • flake8
  • click
  • daemons
  • qutip (optional)
  • projectq (optional)

To verify that that SimulaQron is working on your computer, type:

make verify

in a terminal at the root of the repository. This command will clear any .pyc files in this directory, check that the needed python packages are installed (and if not install these using pip) and run the automated tests. By default a shorter version of the tests are run. If you wish to run the full tests type make full_tests. Not however that the full tests can take quite some time since they perform quantum tomography to tests operations on the qubits. By default the stabilizer engine will be used.


During the tests you might see quite some error messages. This is to be expected since some tests test that errors are handled correctly when something goes wrong. If the tests pass it will say OK in the end.

Testing a simple example

Before delving into how to write any program yourself, let’s first simply run one of the existing examples when programming SimulaQron through the Python library (see Examples using the python library). Remember from the Overview that SimulaQron has two parts: the first are the virtual node servers that act simulate the hardware at each node as well as the quantum communication between them in a transparent manner. The second are the applications themselves which can be written in two ways, the direct way is to use the native mode using the Python Twisted framework connecting to the virtual node servers, see Programming via SimulaQron’s native Python Twisted Interface (specific to SimulaQron). Another way is the use the provided Python library that calls the virtual nodes by making use of the classical/quantum combiner interface. We will here illustrate how to use SimulaQron with the Python library.

Starting the SimulaQron backend

By default SimulaQron uses the five nodes Alice, Bob, Charlie, David and Eve on your local computers. In this example there will be two processes for each node listening to incoming messages on a certain port number. These make up the simulation backend and the CQC server. To start the processes and thus the backend of SimulaQron simply type:

./cli/SimulaQron start


Running ./cli/SimulaQron start will be default start up servers on localhost (i.e., your own computer), using port numbers between 8000 and 9000, to form the simulated quantum internet hardware. SimulaQron does not provide any access control to its simulated hardware, so you are responsible to securing access should this be relevant for you. You can also run the different simulated nodes on different computers. We do not take any responsibility for problems caused by SimulaQron.

For more information on what ./cli/SimulaQron start does, how to change the nodes and the ports of the network, the topology etc, see Configuring the simulated network.

To stop the backend, simply type:

./cli/SimulaQron start

Running a protocol

Having started the virtual quantum nodes as above, let us now run a simple test application, which already illustrates some of the aspects in realizing protocols. Our objective will be to realize the following protocol which will generate 1 shared random bit between Alice and Bob. Evidently, there would be classical means to achieve this trivial task chosen for illustration.

  • Alice and Bob generates one EPR pair, that is, two maximally entangled qubits \(A\) and \(B\) of the form \(|\Psi\rangle_{AB} = \frac{1}{\sqrt{2}} \left(|0\rangle_A |0\rangle_B + |1\rangle_A |1\rangle_B\right)\)
  • Both Alice and Bob measure their respective qubits to obtain a classical random number \(x \in \{0,1\}\).

Before seeing how this example works, let us again simply run the code:

cd examples/cqc/pythonLib/corrRNG

You should be seeing the following two lines:

App Alice: Measurement outcome is: 0/1
App Bob: Measurement outcome is: 0/1

Note that the order of these two lines may differ, as it does not matter who measures first. So what is actually going on here? Let us first look at how we will realize the example by making an additional step (3) explicit:

  • Alice and Bob generate one EPR pair, that is, two maximally entangled qubits \(A\) and \(B\) of the form \(|\Psi\rangle_{AB} = \frac{1}{\sqrt{2}} \left(|0\rangle_A |0\rangle_B + |1\rangle_A |1\rangle_B\right)\)
  • Alice and Bob are informed of the identifiers of the qubits and are informed that entanglement was generated.
  • Both Alice and Bob measure their respective qubits to obtain a classical random number \(x \in \{0,1\}\).

While the task we want to realize here is completely trivial, the addition of step 3 does however already highlight a range of choices on how to realize step 3 and the need to find good abstractions to allow easy application development. One way to realize step 3 would be to hardwire Alices and Bobs measurements: if the hardware can identify the correct qubits from the entanglement generation, then we could instruct it to measure it immediately without asking for a notification from the entanglement generation process. It is clear that in a network that is a bit larger than our tiny three node setup, identifying the right setup requires a link between the underlying qubits and classical control information: this is the objective of the classical/quantum combiner.

The script executes the following two python scripts:


python3 &

Let us now look at the programs for Alice and Bob. We first initialize an object of the class CQCConnection which will do all the communication to the virtual through the CQC interface. Qubits can then be created by initializing a qubit-object, which takes a CQCConnection as an input. On these qubits operations can be applied and they can also be sent to other nodes in the network by use of the CQCConnection. The full code in is:

# Initialize the connection
with CQCConnection("Alice") as Alice:

    # Create an EPR pair
    q = Alice.createEPR("Bob")

    # Measure qubit
    to_print="App {}: Measurement outcome is: {}".format(,m)
    print("| "+to_print+" |")

Similarly the code in read:

# Initialize the connection
with CQCConnection("Bob") as Bob:

    # Receive qubit

    # Measure qubit
    to_print="App {}: Measurement outcome is: {}".format(,m)
    print("| "+to_print+" |")

For further examples, see the examples/ folder.


Settings are stored in the file config/settings.ini and are easily accessed through the command line interface. To see what settings can be set, type:

./cli/SimulaQron set -h

To set a setting, for example to use the projectQ backend, type:

./cli/SimulaQron set backend projectq


Settings needs to be set before starting the SimulaQron backend. If the backend is already running, stop it, set the settings and start it again.

There are also additional settings for CQC backend which can be set in the file cqc/backend/

  • CQC_CONF_RECV_TIMEOUT (default 10 s): The time a node will wait for receiving a qubit before sending back an error message using CQC.
  • CQC_CONF_RECV_EPR_TIMEOUT (default 10 s): The time a node will wait for receiving a qubit part of an EPR pair before sending back an error message using CQC.
  • CQC_CONF_WAIT_TIME_RECV (default 0.1 s): The time between every check if a qubit has been received.
  • CQC_CONF_LINK_WAIT_TIME (default 0.5 s): The time between every try to connect to the CQC server.
  • CQC_CONF_COM_WAIT_TIME (default 0.1 s): The time between every try to connect applications at other nodes for classical communication.