Getting Started

Requirements

Pyquil 2.0, Python 3.6 or higher, and NumPy are requirements for netQuil. You will also need to download the Rigetti’s QVM and Compiler as described on their Getting Started page.

Installation

To install using the Python package manager, pip:

pip install netquil

To install without pip:

easy_install netquil

To instead install netQuil from the source, clone the repository.

git clone https://github.com/att-innovate/netquil.git

Tutorial - Bell State Distribution

Lets start by building our first netQuil program that creates and distributes a bell state pair between Alice and Bob. In this tutorial you will be introduced to Agents (the nodes in your network), QConnections and CConnections (the channels connecting nodes), and Devices (the customizable noise modules and error simulators). Checkout our other demos to see more advanced examples of netQuil in action, and, for bold of you, review our whitepaper to learn about the state of distributed quantum protocols and netQuil.

This tutorial assumes you have a basic understanding of quantum information theory and the pyquil framework built on Quil. For a quick refresher, review this resource.

Import Dependencies

Let’s start by importing all of our dependencies.

1
2
3
from netquil import *
from pyquil import Program
from pyquil.gates import *

Define Agents

Agents are nodes in our quantum network. Each Agent should extend the agent class and define a run function, allowing that agent to run on its own thread. Agents can send and receive quantum and classical information, as well as define source and target devices that ingress and egress information must pass through, respectively. They also maintain local clocks that increment based on traffic and the delay that devices return, a network monitor recording their traffic, and a list of qubits and classical bits that they manage.

All agents should share the same PyQuil program that they can modify to simulate network traffic. The program can be explicitly attached to each agent if presimulation computations must be done, or be omitted to default to a blank program.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
from netquil import *
from pyquil import Program
from pyquil.gates import *

class Alice(Agent):
    def run(self):
       a, b = self.qubits
       p = self.program

class Bob(Agent):
    def run(self):
        pass

alice = Alice(qubits=[0,1])
bob = Bob()

Create the Run Function

An agent’s run function should encapsulate all of the work that agent is responsible for. self.qubits returns the list of qubits that an agent owns and may modify. self.program returns the global program shared between agents, and qsend(name, qubits) and qrecv(name) will send and receive qubits from one agent to another, respectively.

 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Alice(Agent):
    def run(self):
       a, b = self.qubits
       p = self.program

       # Create Bell State
       p += H(a)
       p += CNOT(a,b)

       # Send half of bell state to Bob
       self.qsend('bob', b)

class Bob(Agent):
    def run(self):
        p = self.program

        # Receive half of bell state from Alice
        b = self.qrecv('alice')

        # Measure qubits and run program
        p += Measure(b)

Connect the Agents

QConnect() will create a quantum channel between the given agents. Without establishing this connection, agents have no way of communicating between each other. Similarly CConnect() will create a classical channel between the given agents. Both QConnect() and CConnect() will create channels between all agents passed to them. On QConnect() you may also specify transit_devices which all qubits will travel through when passed between agents.

alice = Alice(qubits=[0,1])
bob = Bob()

# Connect alice and bob to quantum network
QConnect(alice, bob)

Simulate the Network

Simulation(agents...) will start each agent on its own thread and call agents’ run function. Simulation().run will return a list of Quil programs, one for each trial (defaults to one trial), that can be executed on a qvm.

alice = Alice(qubits=[0,1])
bob = Bob()

# Create Quantum Channel between Alice and Bob
QConnect(alice, bob)

programs = Simulation(alice, bob).run()
results = qvm.run(programs[0])
print(results)

Next Steps

All together, your program should look something like this!

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
from netquil import *
from pyquil import Program
from pyquil.gates import *

class Alice(Agent):
    def run(self):
       a, b = self.qubits
       p = self.program

       # Create Bell State
       p += H(a)
       p += CNOT(a,b)

       # Send half of bell state to Bob
       self.qsend('bob', b)

class Bob(Agent):
    def run(self):
        p = self.program

        # Receive half of bell state from Alice
        b = self.qrecv('alice')

        # Measure qubits and run program
        p += Measure(b)

alice = Alice(qubits=[0,1])
bob = Bob()

# Connect alice and bob to quantum network
QConnect(alice, bob)

programs = Simulation(alice, bob).run()
results = qvm.run(programs[0])
print(results)

Congratulations! You now have a working netQuil program that creates and distributes a bell state pair between Alice and Bob.

Explore our advanced usage demo to learn about netQuil’s error module for quantum noise and transit, source and target devices, as well as how to run multiple trials and syncronize agents.

Read the distributed protocol demo to see how the cat-entangler and cat-disentangler can be used to implement non-local CNOTs, non-local controlled gates, and teleportation.

Or, just for fun, checkout the middle-man attack, teleportation, or superdense coding demos to learn about common quantum networking protocols.