Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions docs/source/components/channel_models.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
Channel Models
=======

Channels act as communication modes between the hosts in a network. Each host defines it's quantum and classical
connections with the other hosts in the network. QuNetSim introduces various channel models to mimic the real-world
quantum connections between the hosts.
The default channel model for quantum connections is fibre.

QuNetSim implements the following channel models for quantum connections:

* :code:`BitFlip(probability)`
* Flips the single-qubit (Pauli X) passing through the channel with certain probability
* :code:`PhaseFlip(probability)`
* Flips the phase of the single-qubit (Pauli Z) passing through the channel with certain probability
* :code:`BinaryErasure(probability)`
* Erases the single-qubit passing through the channel with certain probability
* :code:`Fibre(length, alpha)`
* Erases the single-qubit passing through the channel with certain probability determined from the length and absorption coefficient (alpha) of the channel

.. automodule:: qunetsim.components.objects.connections.channel_models
:members:
6 changes: 0 additions & 6 deletions docs/source/components/network.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,6 @@ The most commonly used methods for Network are:
* If the network should recalculate the route at each node in the route (set to True) or just once at the beginning (set to False)
* :code:`(property) delay(float)`
* the amount of delay the network should have. The network has the ability to throttle packet transmissions which is sometimes neccessary for different types of qubit / network backends.
* :code:`(property) packet_drop_rate(float)`
* The probability that a packet is dropped on transmission in the network
* :code:`(property) x_error_rate(float)`
* The probability that a qubit has an :math:`X` gate applied to in at each host in the route
* :code:`(property) z_error_rate(float)`
* The probability that a qubit has an :math:`Z` gate applied to in at each host in the route
* :code:`draw_classical_network`
* Generate a depiction of the classical network
* :code:`draw_quantum_network`
Expand Down
16 changes: 8 additions & 8 deletions docs/source/examples/QKD_BB84.rst
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,10 @@ the same bit again, until the transmission works.
if base == 1:
q_bit.H()

# Send Qubit to Bob
# Send Qubit to Eve
alice.send_qubit(receiver, q_bit, await_ack=True)

# Get measured basis of Bob
# Get measured basis of Eve
message = alice.get_next_classical_message(receiver, msg_buff, sequence_nr)

# Compare to send basis, if same, answer with 0 and set ack True and go to next bit,
Expand Down Expand Up @@ -130,7 +130,7 @@ the same bit again, until the transmission works.
q_bit.H()
bit = q_bit.measure()

# Send Alice the base in which Bob has measured
# Send Alice the base in which Eve has measured
eve.send_classical(sender, "%d:%d" % (sequence_nr, measurement_base), await_ack=True)

# get the return message from Alice, to know if the bases have matched
Expand Down Expand Up @@ -211,7 +211,7 @@ We can now concatenate the two actions of Alice and Eve and let them each run in
eve_key = eve_qkd(eve, msg_buff, key_size, host_alice.host_id)
eve_receive_message(eve, msg_buff, eve_key, host_alice.host_id)

# Run Bob and Alice
# Run Eve and Alice

t1 = host_alice.run_protocol(alice_func, ())
t2 = host_eve.run_protocol(eve_func, ())
Expand Down Expand Up @@ -275,10 +275,10 @@ The full example is below:
if base == 1:
q_bit.H()

# Send Qubit to Bob
# Send Qubit to Eve
alice.send_qubit(receiver, q_bit, await_ack=True)

# Get measured basis of Bob
# Get measured basis of Eve
message = alice.get_next_classical_message(receiver, msg_buff, sequence_nr)

# Compare to send basis, if same, answer with 0 and set ack True and go to next bit,
Expand Down Expand Up @@ -312,7 +312,7 @@ The full example is below:
q_bit.H()
bit = q_bit.measure()

# Send Alice the base in which Bob has measured
# Send Alice the base in which Eve has measured
eve.send_classical(sender, "%d:%d" % (sequence_nr, measurement_base), await_ack=True)

# get the return message from Alice, to know if the bases have matched
Expand Down Expand Up @@ -404,7 +404,7 @@ The full example is below:
eve_key = eve_qkd(eve, msg_buff, key_size, host_alice.host_id)
eve_receive_message(eve, msg_buff, eve_key, host_alice.host_id)

# Run Bob and Alice
# Run Eve and Alice

t1 = host_alice.run_protocol(alice_func, ())
t2 = host_eve.run_protocol(eve_func, ())
Expand Down
1 change: 1 addition & 0 deletions docs/source/examples/entanglement_routing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ The full example is below.
from qunetsim.objects import Logger
import networkx
import time
import random


def generate_entanglement(host):
Expand Down
4 changes: 2 additions & 2 deletions docs/source/examples/packet_sniffing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ We set these protocols to the hosts via the following code:
:linenos:

host_bob.q_relay_sniffing = True
host_bob.q_relay_sniffing_fn = eve_sniffing_quantum
host_bob.q_relay_sniffing_fn = bob_sniffing_quantum

host_bob.c_relay_sniffing = True
host_bob.c_relay_sniffing_fn = bob_sniffing_classical
Expand Down Expand Up @@ -196,7 +196,7 @@ The full example is below.
network.add_host(host_eve)

host_bob.q_relay_sniffing = True
host_bob.q_relay_sniffing_fn = eve_sniffing_quantum
host_bob.q_relay_sniffing_fn = bob_sniffing_quantum

host_bob.c_relay_sniffing = True
host_bob.c_relay_sniffing_fn = bob_sniffing_classical
Expand Down
1 change: 0 additions & 1 deletion docs/source/examples/quantum_money.rst
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,6 @@ The full example is below:
from qunetsim.objects import Logger
from qunetsim.objects import Qubit
from random import randint, random
from qunetsim.backends import ProjectQBackend

Logger.DISABLED = True

Expand Down
2 changes: 1 addition & 1 deletion docs/source/examples/send_epr.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Send EPR Pairs
--------------

In this example, we'll see how to generate a network with 4 nodes as in the figure below.
In this example, we'll see how to generate a network with 3 nodes connected in a linear fashion.
We'll then send an EPR pair from one end of the link to the other. The example shows
how to build a network and a simple application.

Expand Down
4 changes: 2 additions & 2 deletions docs/source/examples/send_w.rst
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ then the system density matrix is printed and a measurement on each participant
q4 = host_dean.get_w('Alice', q_id1, wait=10)

print("System density matrix:")
print(q1._qubit[0].data)
print(q1.density_operator())

m1 = q1.measure()
m2 = q2.measure()
Expand Down Expand Up @@ -154,7 +154,7 @@ The full example is below:
q4 = host_dean.get_w('Alice', q_id1, wait=10)

print("System density matrix:")
print(q1._qubit[0].data)
print(q1.density_operator())

m1 = q1.measure()
m2 = q2.measure()
Expand Down
8 changes: 8 additions & 0 deletions integration_tests/test_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ def setUpClass(cls):
def tearDownClass(cls):
pass

def test_qubit_initialization(self):
backend = EQSNBackend()
host_alice = Host('Alice', backend)
qubit_initialized = Qubit(host_alice, theta=np.pi/2, phi=np.pi/2)

self.assertAlmostEqual(host_alice.backend.eqsn.give_statevector_for(qubit_initialized.qubit)[1][0], 0.5-0.5j)
self.assertAlmostEqual(host_alice.backend.eqsn.give_statevector_for(qubit_initialized.qubit)[1][1], 0.5+0.5j)

# @unittest.skip('')
def test_epr_generation(self):
for b in TestBackend.backends:
Expand Down
100 changes: 99 additions & 1 deletion integration_tests/test_host.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import unittest
import numpy as np

from qunetsim.objects import Qubit
from qunetsim.components import Host
from random import randint

from qunetsim.components.network import Network
from qunetsim.objects.connections.channel_models import BitFlip, ClassicalModel, PhaseFlip, BinaryErasure, Fibre

# @unittest.skip('')
class TestHost(unittest.TestCase):
Expand Down Expand Up @@ -180,6 +182,24 @@ def test_add_connections(self):
self.assertEqual(len(a.classical_connections), 6)
self.assertEqual(len(a.quantum_connections), 6)

def test_connection_models(self):
a = Host('A')

a.add_c_connection('B', ClassicalModel())
self.assertEqual(a.classical_connections['B'].model.type, "Classical")
with self.assertRaises(Exception):
a.add_c_connection('C', BitFlip())
self.assertEqual(len(a.classical_connections), 1)

a.add_q_connection('D', BitFlip(0.5))
self.assertEqual(a.quantum_connections['D'].model.type, "Quantum")
a.add_q_connection('E', PhaseFlip(0.1))
self.assertEqual(a.quantum_connections['E'].model.type, "Quantum")
a.add_q_connection('F', BinaryErasure(0.2))
self.assertEqual(a.quantum_connections['F'].model.type, "Quantum")
a.add_q_connection('G', Fibre(alpha=0.3))
self.assertEqual(a.quantum_connections['G'].model.type, "Quantum")

def test_remove_connections(self):
a = Host('A')
a.add_connections(['B', 'C'])
Expand All @@ -197,3 +217,81 @@ def test_remove_connections(self):
a.remove_connection('C')
self.assertEqual(len(a.classical_connections), 0)
self.assertEqual(len(a.quantum_connections), 0)

def test_kwargs_runprotocol(self):
def bob_do(host, sender):
q = host.get_qubit(sender.host_id, wait=10)
self.assertNotEqual(q, None)
self.assertAlmostEqual(host.backend.eqsn.give_statevector_for(q.qubit)[1][0], 0.5-0.5j)

def alice_do(host, receiver, theta, phi):
q = Qubit(host)
q.ry(theta)
q.rz(phi)
_, ack = host.send_qubit(receiver.host_id, q, await_ack=True)

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

network.add_host(host_alice)
network.add_host(host_bob)
network.start()

t1 = host_alice.run_protocol(alice_do, kwargs={'theta':np.pi/2, 'receiver':host_bob, 'phi':np.pi/2})
t2 = host_bob.run_protocol(bob_do, kwargs={'sender':host_alice}, blocking=True)
t1.join()

s1 = host_alice.run_protocol(alice_do, (host_bob, np.pi/2, np.pi/2))
s2 = host_bob.run_protocol(bob_do, (host_alice,), blocking=True)
s1.join()

def test_send_n_qubits(self):
def sender_do(host, receiver, num_qubits, recv_ack=False):
global q_id_list
if recv_ack:
q_id_list, ack_arr = host.send_qubits(receiver.host_id, host.make_list_n_qubits(num_qubits), await_ack=recv_ack)
self.assertEqual(len(ack_arr), num_qubits)
else:
q_id_list = host.send_qubits(receiver.host_id, host.make_list_n_qubits(num_qubits), await_ack=recv_ack)
self.assertEqual(len(q_id_list), num_qubits)

def receiver_do(host, sender, num_qubits):
global q_id_received
q_id_received = []
while len(q_id_received) < num_qubits:
qubit_recv = host.get_qubit(sender.host_id, wait=10)
if qubit_recv is not None:
q_id_received.append(qubit_recv.id)
self.assertEqual(len(q_id_received), num_qubits)

network = Network.get_instance()
nodes = ['sender', 'receiver']
network.start(nodes)

host_sender = Host('sender')
host_sender.add_connection('receiver')
host_sender.start()

host_receiver = Host('receiver')
host_receiver.add_connection('sender')
host_receiver.start()

network.add_host(host_sender)
network.add_host(host_receiver)
network.start()

host_sender.run_protocol(sender_do, kwargs={'num_qubits':5, 'receiver': host_receiver, 'recv_ack': True}, blocking=True)
host_receiver.run_protocol(receiver_do, kwargs={'num_qubits':5, 'sender': host_sender}, blocking=True)

network.stop(True)
self.assertEqual(set(q_id_list), set(q_id_received))

Loading