Send Data Qubits

In this example, we send a data qubit from Alice to Dean who sits 2 hops away from Alice in the network.

First we configure the network.

 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
network = Network.get_instance()
nodes = ["Alice", "Bob", "Eve", "Dean"]
network.start(nodes)

host_alice = Host('Alice')
host_alice.add_connection('Bob')
host_alice.start()

host_bob = Host('Bob')
host_bob.add_connection('Alice')
host_bob.add_connection('Eve')
host_bob.start()

host_eve = Host('Eve')
host_eve.add_connection('Bob')
host_eve.add_connection('Dean')
host_eve.start()

host_dean = Host('Dean')
host_dean.add_connection('Eve')
host_dean.start()

# Network will be:
# Alice <==> Bob <==> Eve <==> Dean
# Note: we use 'A<==>B' to represent a classical and quantum connection
#       we use 'A<-->B' to represent a classical only connection
#       we use 'A<~~>B' to represent a quantum only connection
#       All connections are added uni-directionally, so '<' and '>'
#       represent the direction of the flow of traffic.


network.add_host(host_alice)
network.add_host(host_bob)
network.add_host(host_eve)
network.add_host(host_dean)

Now, the Host Alice will send 10 qubits to Dean after applying an X gate on the qubit. She will then wait for an acknowledgement from Dean before continuing, that is, line 7 below will block until an ACK arrives at Alice. Alice has a setting, Host.max_ack_wait, that tells her to wait for the set time before assuming that either the packet didn’t arrive at Dean, or the ACK was lost. Because the flag await_ack is set to true, send_qubit will return two values: the qubit ID that was sent, and a boolean value that says if the ACK arrived, or Alice exceeded the maximum waiting time.

In QuNetSim, there are two ways of writing protocols. Here we see what we will call the linear style. What this means is that all of the hosts are being accessed at the same place in the code. In the next example, we will see what we will call a parallel style, where the programmer of the simulation has access to one host at a time, and has to add logic to the protocol to transmit needed information to the communicating parties. Each host will run their part of the protocol, but can’t access any information from other hosts directly.

With this in mind, we see that on line 10, because Alice awaited the ACK from Dean, and line 7 is blocking, Dean can safely access the qubit that Alice sent without having to wait.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
for _ in range(10):
    # Create a qubit owned by Alice
    q = Qubit(host_alice)
    # Put the qubit in the excited state
    q.X()
    # Send the qubit and await an ACK from Dean
    q_id, ack_arrived = host_alice.send_qubit('Dean', q, await_ack=True)

    # Get the qubit on Dean's side from Alice
    q_rec = host_dean.get_qubit('Alice', q_id, wait=0)

    # Ensure the qubit arrived and then measure and print the results.
    if q_rec is not None:
        m = q_rec.measure()
        print("Results of the measurements for q_id are ", str(m))
    else:
        print('Qubit did not arrive.')

In the next example, we’ll see something similar using the parallel style.

The full example is below:

 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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
from qunetsim.components import Host
from qunetsim.components import Network
from qunetsim.objects import Qubit


def main():
    network = Network.get_instance()
    nodes = ["Alice", "Bob", "Eve", "Dean"]
    network.start(nodes)
    network.delay = 0.1

    host_alice = Host('Alice')
    host_alice.add_connection('Bob')
    host_alice.start()

    host_bob = Host('Bob')
    host_bob.add_connection('Alice')
    host_bob.add_connection('Eve')
    host_bob.start()

    host_eve = Host('Eve')
    host_eve.add_connection('Bob')
    host_eve.add_connection('Dean')
    host_eve.start()

    host_dean = Host('Dean')
    host_dean.add_connection('Eve')
    host_dean.start()

    network.add_host(host_alice)
    network.add_host(host_bob)
    network.add_host(host_eve)
    network.add_host(host_dean)

    for _ in range(10):
        # Create a qubit owned by Alice
        q = Qubit(host_alice)
        # Put the qubit in the excited state
        q.X()
        # Send the qubit and await an ACK from Dean
        q_id, _ = host_alice.send_qubit('Dean', q, await_ack=True)

        # Get the qubit on Dean's side from Alice
        q_rec = host_dean.get_qubit('Alice', q_id)

        # Ensure the qubit arrived and then measure and print the results.
        if q_rec is not None:
            m = q_rec.measure()
            print("Results of the measurements for q_id are ", str(m))
        else:
            print('q_rec is none')

    # Stop the network at the end of the example
    network.stop(stop_hosts=True)

if __name__ == '__main__':
    main()