-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Expanded API documentation to include utility methods and routines
* Expanded tutorial documentation with a section for multiple nodes * Added utility method create_complete_graph_network * Various fixes for properly displaying API documentation * Reworked the tutorial example 4.3_multi-node to a completly different example * Edited the GHZ example to use the new squidASM utility method for generating the complete graph network instead of the netbuilder utility method
- Loading branch information
1 parent
3864cf8
commit 639ede3
Showing
9 changed files
with
285 additions
and
74 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
Routines | ||
========== | ||
|
||
.. automodule:: squidasm.util.routines | ||
:members: | ||
:undoc-members: | ||
|
||
.. automodule:: squidasm.util.qkd_routine | ||
:members: | ||
:undoc-members: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
.. _label_API_util: | ||
|
||
|
||
Util | ||
========== | ||
|
||
.. automodule:: squidasm.util.util | ||
:members: | ||
:undoc-members: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,82 +1,134 @@ | ||
from typing import List | ||
|
||
import netsquid as ns | ||
from netqasm.sdk.classical_communication.socket import Socket | ||
from netqasm.sdk.connection import BaseNetQASMConnection | ||
from netqasm.sdk.epr_socket import EPRSocket | ||
|
||
from squidasm.sim.stack.program import Program, ProgramContext, ProgramMeta | ||
|
||
|
||
class ClientProgram(Program): | ||
def __init__(self, name: str, server_name: str): | ||
self.name = name | ||
self.server_name = server_name | ||
class AliceProgram(Program): | ||
PEER_BOB = "Bob" | ||
PEER_CHARLIE = "Charlie" | ||
|
||
@property | ||
def meta(self) -> ProgramMeta: | ||
return ProgramMeta( | ||
name="tutorial_program", | ||
csockets=[self.server_name], | ||
epr_sockets=[self.server_name], | ||
max_qubits=1, | ||
csockets=[self.PEER_BOB, self.PEER_CHARLIE], | ||
epr_sockets=[self.PEER_BOB, self.PEER_CHARLIE], | ||
max_qubits=2, | ||
) | ||
|
||
def run(self, context: ProgramContext): | ||
# get classical socket to peer | ||
csocket = context.csockets[self.server_name] | ||
# get EPR socket to peer | ||
epr_socket = context.epr_sockets[self.server_name] | ||
# get classical sockets | ||
csocket_bob = context.csockets[self.PEER_BOB] | ||
csocket_charlie = context.csockets[self.PEER_CHARLIE] | ||
# get EPR sockets | ||
epr_socket_bob = context.epr_sockets[self.PEER_BOB] | ||
epr_socket_charlie = context.epr_sockets[self.PEER_CHARLIE] | ||
# get connection to quantum network processing unit | ||
connection = context.connection | ||
|
||
# Bob listens for messages on his classical socket | ||
message = yield from csocket.recv() | ||
print(f"{ns.sim_time()} ns: Client: {self.name} receives message: {message}") | ||
|
||
# Listen for request to create EPR pair, apply a Hadamard gate on the epr qubit and measure | ||
epr_qubit = epr_socket.recv_keep()[0] | ||
epr_qubit.H() | ||
result = epr_qubit.measure() | ||
# send a message to both nodes | ||
msg = "Hello from Alice" | ||
csocket_bob.send(msg) | ||
csocket_charlie.send(msg) | ||
print(f"{ns.sim_time()} ns: Alice sends: {msg} to Bob and Charlie") | ||
|
||
# Generate EPR pairs with both Bob and Charlie | ||
epr_qubit_bob = epr_socket_bob.create_keep()[0] | ||
epr_qubit_charlie = epr_socket_charlie.create_keep()[0] | ||
# Perform a bell state measurement on the qubit from Bob and the qubit from Charlie | ||
epr_qubit_bob.cnot(epr_qubit_charlie) | ||
epr_qubit_bob.H() | ||
m2 = epr_qubit_bob.measure() | ||
m1 = epr_qubit_charlie.measure() | ||
yield from connection.flush() | ||
|
||
print( | ||
f"{ns.sim_time()} ns: Client: {self.name} measures local EPR qubit: {result}" | ||
f"{ns.sim_time()} ns: Alice finished EPR generation and local quantum operations" | ||
) | ||
csocket_charlie.send(str(int(m2))) | ||
csocket_charlie.send(str(int(m1))) | ||
|
||
print( | ||
f"{ns.sim_time()} ns: Alice sends corrections m1: {m1}, m2: {m2} to Charlie" | ||
) | ||
|
||
return {} | ||
|
||
|
||
class ServerProgram(Program): | ||
def __init__(self, clients: List[str]): | ||
self.clients = clients | ||
class BobProgram(Program): | ||
PEER = "Alice" | ||
|
||
@property | ||
def meta(self) -> ProgramMeta: | ||
return ProgramMeta( | ||
name="tutorial_program", | ||
csockets=self.clients, | ||
epr_sockets=self.clients, | ||
csockets=[self.PEER], | ||
epr_sockets=[self.PEER], | ||
max_qubits=1, | ||
) | ||
|
||
def run(self, context: ProgramContext): | ||
connection: BaseNetQASMConnection = context.connection | ||
# get classical sockets | ||
csocket = context.csockets[self.PEER] | ||
# get EPR sockets | ||
epr_socket = context.epr_sockets[self.PEER] | ||
# get connection to quantum network processing unit | ||
connection = context.connection | ||
|
||
for client in self.clients: | ||
# get classical socket to peer | ||
csocket: Socket = context.csockets[client] | ||
epr_socket: EPRSocket = context.epr_sockets[client] | ||
msg = yield from csocket.recv() | ||
print(f"{ns.sim_time()} ns: Bob receives: {msg}") | ||
|
||
# send a string message via a classical channel | ||
message = f"Client: {client} you may start" | ||
csocket.send(message) | ||
print(f"{ns.sim_time()} ns: Server sends message: {message}") | ||
# Generate and measure EPR pair with Alice | ||
qubit = epr_socket.recv_keep()[0] | ||
result = qubit.measure() | ||
yield from connection.flush() | ||
print( | ||
f"{ns.sim_time()} ns: Bob finished EPR generation and measures his qubit: {result}" | ||
) | ||
|
||
# Register a request to create an EPR pair, then apply a Hadamard gate on the epr qubit and measure | ||
epr_qubit = epr_socket.create_keep()[0] | ||
epr_qubit.H() | ||
result = epr_qubit.measure() | ||
yield from connection.flush() | ||
print(f"{ns.sim_time()} ns: Server measures local EPR qubit: {result}") | ||
|
||
return {} | ||
class CharlieProgram(Program): | ||
PEER = "Alice" | ||
|
||
@property | ||
def meta(self) -> ProgramMeta: | ||
return ProgramMeta( | ||
name="tutorial_program", | ||
csockets=[self.PEER], | ||
epr_sockets=[self.PEER], | ||
max_qubits=1, | ||
) | ||
|
||
def run(self, context: ProgramContext): | ||
# get classical sockets | ||
csocket = context.csockets[self.PEER] | ||
# get EPR sockets | ||
epr_socket = context.epr_sockets[self.PEER] | ||
# get connection to quantum network processing unit | ||
connection = context.connection | ||
|
||
msg = yield from csocket.recv() | ||
print(f"{ns.sim_time()} ns: Charlie receives: {msg}") | ||
|
||
# Generate EPR pair with Alice | ||
qubit = epr_socket.recv_keep()[0] | ||
yield from connection.flush() | ||
print(f"{ns.sim_time()} ns: Carlie finished EPR generation") | ||
|
||
# Receive corrections from Alice | ||
m2 = yield from csocket.recv() | ||
m1 = yield from csocket.recv() | ||
print(f"{ns.sim_time()} ns: Carlie received corrections: m1: {m1}, m2: {m2}") | ||
|
||
# Apply corrections | ||
if int(m1): | ||
qubit.X() | ||
if int(m2): | ||
qubit.Z() | ||
|
||
# Measure the EPR qubit | ||
result = qubit.measure() | ||
yield from connection.flush() | ||
print( | ||
f"{ns.sim_time()} ns: Carlie applied corrections and measures his qubit {result}" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
# 3 node network, all the sources of noise have been disabled for this example | ||
qdevice_cfg: &qdevice_cfg | ||
num_qubits: 2 | ||
|
||
# coherence times (same for each qubit) | ||
T1: 0 | ||
T2: 0 | ||
|
||
# gate execution times | ||
init_time: 10_000 | ||
single_qubit_gate_time: 1_000 | ||
two_qubit_gate_time: 100_000 | ||
measure_time: 10_000 | ||
|
||
# noise model | ||
single_qubit_gate_depolar_prob: 0. | ||
two_qubit_gate_depolar_prob: 0. | ||
|
||
stacks: | ||
- name: Alice | ||
qdevice_typ: generic | ||
qdevice_cfg: | ||
<<: *qdevice_cfg | ||
|
||
- name: Bob | ||
qdevice_typ: generic | ||
qdevice_cfg: | ||
<<: *qdevice_cfg | ||
|
||
- name: Charlie | ||
qdevice_typ: generic | ||
qdevice_cfg: | ||
<<: *qdevice_cfg | ||
|
||
|
||
link_cfg: &link_cfg | ||
fidelity: 1 | ||
prob_success: 0.3 | ||
t_cycle: 1e5 | ||
|
||
links: | ||
- stack1: Alice | ||
stack2: Bob | ||
typ: depolarise | ||
cfg: | ||
<<: *link_cfg | ||
- stack1: Alice | ||
stack2: Charlie | ||
typ: depolarise | ||
cfg: | ||
<<: *link_cfg | ||
- stack1: Bob | ||
stack2: Charlie | ||
typ: depolarise | ||
cfg: | ||
<<: *link_cfg | ||
|
||
clinks: | ||
- stack1: Alice | ||
stack2: Bob | ||
typ: default | ||
cfg: | ||
delay: 5e3 | ||
- stack1: Alice | ||
stack2: Charlie | ||
typ: default | ||
cfg: | ||
delay: 1e4 | ||
- stack1: Bob | ||
stack2: Charlie | ||
typ: default | ||
cfg: | ||
delay: 1e4 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,29 +1,19 @@ | ||
from application import ClientProgram, ServerProgram | ||
from netsquid_netbuilder.modules.clinks.default import DefaultCLinkConfig | ||
from netsquid_netbuilder.modules.links.perfect import PerfectLinkConfig | ||
from netsquid_netbuilder.util.network_generation import create_complete_graph_network | ||
from application import AliceProgram, BobProgram, CharlieProgram | ||
|
||
from squidasm.run.stack.config import StackNetworkConfig | ||
from squidasm.run.stack.run import run | ||
|
||
num_nodes = 6 | ||
node_names = [f"Node_{i}" for i in range(num_nodes)] | ||
|
||
# import network configuration from file | ||
cfg = create_complete_graph_network( | ||
node_names, | ||
"perfect", | ||
PerfectLinkConfig(state_delay=100), | ||
clink_typ="default", | ||
clink_cfg=DefaultCLinkConfig(delay=100), | ||
) | ||
cfg = StackNetworkConfig.from_file("config.yaml") | ||
|
||
server_name = node_names[0] | ||
client_names = node_names[1:] | ||
# Create instances of programs to run | ||
alice_program = AliceProgram() | ||
bob_program = BobProgram() | ||
charlie_program = CharlieProgram() | ||
|
||
programs = {server_name: ServerProgram(clients=client_names)} | ||
for client in client_names: | ||
programs[client] = ClientProgram(client, server_name) | ||
|
||
# Run the simulation. Programs argument is a mapping of network node labels to programs to run on that node | ||
run(config=cfg, programs=programs, num_times=1) | ||
run( | ||
config=cfg, | ||
programs={"Alice": alice_program, "Bob": bob_program, "Charlie": charlie_program}, | ||
num_times=1, | ||
) |
Oops, something went wrong.