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
12 changes: 3 additions & 9 deletions integration_tests/test_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,7 @@ def test_epr_generation(self):

# Test multiple times to eliminate probabilistic effects
for _ in range(5):
q1 = backend.create_EPR(alice.host_id, bob.host_id)
q2 = backend.receive_epr(
bob.host_id, alice.host_id, q_id=q1.id)
q1, q2 = backend.create_EPR(alice.host_id, bob.host_id)
self.assertEqual(q1.id, q2.id)
self.assertEqual(backend.measure(q1, False),
backend.measure(q2, False))
Expand Down Expand Up @@ -87,9 +85,7 @@ def test_density_operator_qutip(self):
network.add_host(alice)
network.add_host(bob)

q1 = backend.create_EPR(alice.host_id, bob.host_id)
q2 = backend.receive_epr(
bob.host_id, alice.host_id, q_id=q1.id)
q1, q2 = backend.create_EPR(alice.host_id, bob.host_id)

density_operator = backend.density_operator(q1)
expected = np.diag([0.5, 0.5])
Expand All @@ -116,9 +112,7 @@ def test_density_operator(self):
network.add_host(alice)
network.add_host(bob)

q1 = backend.create_EPR(alice.host_id, bob.host_id)
q2 = backend.receive_epr(
bob.host_id, alice.host_id, q_id=q1.id)
q1, q2 = backend.create_EPR(alice.host_id, bob.host_id)

density_operator = backend.density_operator(q1)
expected = np.diag([0.5, 0.5])
Expand Down
25 changes: 4 additions & 21 deletions qunetsim/backends/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,33 +57,16 @@ def send_qubit_to(self, qubit, from_host_id, to_host_id):
raise (EnvironmentError("This is only an interface, not \
an actual implementation!"))

def create_EPR(self, host_a_id, host_b_id, q_id=None, block=False):
def create_EPR(self, host_id, q_id=None, block=False):
"""
Creates an EPR pair for two qubits and returns one of the qubits.
Creates an EPR pair for two qubits and returns both of the qubits.

Args:
host_a_id (String): ID of the first host who gets the EPR state.
host_b_id (String): ID of the second host who gets the EPR state.
host_id (String): ID of the host who creates the EPR state.
q_id (String): Optional id which both qubits should have.
block (bool): Determines if the created pair should be blocked or not.
Returns:
Returns a qubit. The qubit belongs to host a. To get the second
qubit of host b, the receive_epr function has to be called.
"""
raise (EnvironmentError("This is only an interface, not \
an actual implementation!"))

def receive_epr(self, host_id, sender_id, q_id=None, block=False):
"""
Called after create EPR in the receiver, to receive the other EPR pair.

Args:
host_id (String): ID of the first host who gets the EPR state.
sender_id (String): ID of the sender of the EPR pair.
q_id (String): Optional id which both qubits should have.
block (bool): Determines if the created pair should be blocked or not.
Returns:
Returns an EPR qubit with the other Host.
Returns both EPR qubits.
"""
raise (EnvironmentError("This is only an interface, not \
an actual implementation!"))
Expand Down
72 changes: 9 additions & 63 deletions qunetsim/backends/cqc_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,23 +46,6 @@ def __init__(self):
CQCBackend.CQCConnections.__instance = self
SafeDict.__init__(self)

class EntanglementIDs(SafeDict):
# There only should be one instance of Hosts
__instance = None

@staticmethod
def get_instance():
if CQCBackend.EntanglementIDs.__instance is not None:
return CQCBackend.EntanglementIDs.__instance
else:
return CQCBackend.EntanglementIDs()

def __init__(self):
if CQCBackend.EntanglementIDs.__instance is not None:
raise Exception("Call get instance to get this class!")
CQCBackend.EntanglementIDs.__instance = self
SafeDict.__init__(self)

# SimulaQron comes with an own network simulator
# has to be kept in sync with QuNetSim network
backend_network = None
Expand All @@ -71,8 +54,6 @@ def __init__(self):
def __init__(self):
self._hosts = CQCBackend.Hosts.get_instance()
self._cqc_connections = CQCBackend.CQCConnections.get_instance()
# keys are from : to, where from is the host calling create EPR
self._entaglement_ids = CQCBackend.EntanglementIDs.get_instance()
self._stopped = False

def start(self, **kwargs):
Expand Down Expand Up @@ -139,7 +120,7 @@ def send_qubit_to(self, qubit, from_host_id, to_host_id):
qubit.qubit = cqc_to_host.recvQubit()
qubit.host = self._hosts.get_from_dict(to_host_id)

def create_EPR(self, host_a_id, host_b_id, q_id=None, block=False):
def create_EPR(self, host_id, q_id=None, block=False):
"""
Creates an EPR pair for two qubits and returns one of the qubits.

Expand All @@ -152,50 +133,15 @@ def create_EPR(self, host_a_id, host_b_id, q_id=None, block=False):
Returns a qubit. The qubit belongs to host a. To get the second
qubit of host b, the receive_epr function has to be called.
"""
cqc_host_a = self._cqc_connections.get_from_dict(host_a_id)
cqc_host_b = self._cqc_connections.get_from_dict(host_b_id)
host_a = self._hosts.get_from_dict(host_a_id)
q = cqc_host_a.createEPR(cqc_host_b.name)
qubit = Qubit(host_a, qubit=q, q_id=q_id, blocked=block)
# add the ID to a list, so the next returned qubit from recv EPR
# gets assigned the right id
self.store_ent_id(cqc_host_a, cqc_host_b, qubit)
return qubit

def store_ent_id(self, cqc_host_a, cqc_host_b, qubit):
key = cqc_host_a.name + ':' + cqc_host_b.name
ent_list = self._entaglement_ids.get_from_dict(key)
if ent_list is not None:
ent_list.append(qubit.id)
else:
ent_list = [qubit.id]
self._entaglement_ids.add_to_dict(key, ent_list)

def receive_epr(self, host_id, sender_id, q_id=None, block=False):
"""
Called after create EPR in the receiver, to receive the other EPR pair.

Args:
host_id (String): ID of the first host who gets the EPR state.
sender_id (String): ID of the sender of the EPR pair.
q_id (String): Optional id which both qubits should have.
block (bool): Determines if the created pair should be blocked or not.
Returns:
Returns an EPR qubit with the other Host.
"""
cqc_host = self._cqc_connections.get_from_dict(host_id)
host = self._hosts.get_from_dict(host_id)
q = cqc_host.recvEPR()
key = sender_id + ':' + cqc_host.name
ent_list = self._entaglement_ids.get_from_dict(key)
if ent_list is None:
raise Exception("Internal Error!")
id = None
id = ent_list.pop(0)
if q_id is not None and q_id != id:
raise ValueError("q_id doesn't match id!")
self._entaglement_ids.add_to_dict(key, ent_list)
return Qubit(host, qubit=q, q_id=id, blocked=block)
cqc_host = self._cqc_connections.get_from_dict(host_id)
q1 = cqc.qubit(cqc_host)
q2 = cqc.qubit(cqc_host)
q1.H()
q1.cnot(q2)
q1 = Qubit(host, qubit=q1, q_id=id, blocked=block)
q2 = Qubit(host, qubit=q2, q_id=id, blocked=block)
return q1, q2

def flush(self, host_id):
"""
Expand Down
72 changes: 8 additions & 64 deletions qunetsim/backends/eqsn_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,27 +99,8 @@ def __init__(self):
EQSNBackend.Hosts.__instance = self
SafeDict.__init__(self)

class EntanglementIDs(SafeDict):
# There only should be one instance of Hosts
__instance = None

@staticmethod
def get_instance():
if EQSNBackend.EntanglementIDs.__instance is not None:
return EQSNBackend.EntanglementIDs.__instance
else:
return EQSNBackend.EntanglementIDs()

def __init__(self):
if EQSNBackend.EntanglementIDs.__instance is not None:
raise Exception("Call get instance to get this class!")
EQSNBackend.EntanglementIDs.__instance = self
SafeDict.__init__(self)

def __init__(self):
self._hosts = EQSNBackend.Hosts.get_instance()
# keys are from : to, where from is the host calling create EPR
self._entaglement_qubits = EQSNBackend.EntanglementIDs.get_instance()
self.eqsn = EQSN.get_instance()

def start(self, **kwargs):
Expand Down Expand Up @@ -170,64 +151,27 @@ def send_qubit_to(self, qubit, from_host_id, to_host_id):
new_host = self._hosts.get_from_dict(to_host_id)
qubit.host = new_host

def create_EPR(self, host_a_id, host_b_id, q_id=None, block=False):
def create_EPR(self, host_id, q_id=None, block=False):
"""
Creates an EPR pair for two qubits and returns one of the qubits.
Creates an EPR pair for two qubits and returns both of the qubits.

Args:
host_a_id (String): ID of the first host who gets the EPR state.
host_b_id (String): ID of the second host who gets the EPR state.
host_id (String): ID of the host who creates the EPR state.
q_id (String): Optional id which both qubits should have.
block (bool): Determines if the created pair should be blocked or not.
Returns:
Returns a qubit. The qubit belongs to host a. To get the second
qubit of host b, the receive_epr function has to be called.
Returns both EPR qubits.
"""
uid1 = uuid.uuid4()
uid2 = uuid.uuid4()
host_a = self._hosts.get_from_dict(host_a_id)
host_b = self._hosts.get_from_dict(host_b_id)
host = self._hosts.get_from_dict(host_id)
self.eqsn.new_qubit(uid1)
self.eqsn.new_qubit(uid2)
self.eqsn.H_gate(uid1)
self.eqsn.cnot_gate(uid2, uid1)
q1 = Qubit(host_a, qubit=uid1, q_id=q_id, blocked=block)
q2 = Qubit(host_b, qubit=uid2, q_id=q1.id, blocked=block)
self.store_ent_pair(host_a.host_id, host_b.host_id, q2)
return q1

def store_ent_pair(self, host_a, host_b, qubit):
key = host_a + ':' + host_b
ent_queue = self._entaglement_qubits.get_from_dict(key)

if ent_queue is not None:
ent_queue.put(qubit)
else:
ent_queue = Queue()
ent_queue.put(qubit)
self._entaglement_qubits.add_to_dict(key, ent_queue)

def receive_epr(self, host_id, sender_id, q_id=None, block=False):
"""
Called after create EPR in the receiver, to receive the other EPR pair.

Args:
host_id (String): ID of the first host who gets the EPR state.
sender_id (String): ID of the sender of the EPR pair.
q_id (String): Optional id which both qubits should have.
block (bool): Determines if the created pair should be blocked or not.
Returns:
Returns an EPR qubit with the other Host.
"""
key = sender_id + ':' + host_id
ent_queue = self._entaglement_qubits.get_from_dict(key)
if ent_queue is None:
raise Exception("Internal Error!")
q = ent_queue.get()
self._entaglement_qubits.add_to_dict(key, ent_queue)
if q_id is not None and q_id != q.id:
raise ValueError("Qid doesent match id!")
return q
q1 = Qubit(host, qubit=uid1, q_id=q_id, blocked=block)
q2 = Qubit(host, qubit=uid2, q_id=q1.id, blocked=block)
return q1, q2

##########################
# Gate definitions #
Expand Down
74 changes: 10 additions & 64 deletions qunetsim/backends/projectq_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,30 +15,12 @@
class ProjectQBackend(object):
def __init__(self):
self._hosts = ProjectQBackend.Hosts.get_instance()
self._entaglement_pairs = ProjectQBackend.EntanglementPairs.get_instance()
self.engine = projectq.MainEngine()
self.measuring = False

def __del__(self):
self.engine.flush(deallocate_qubits=True)

class EntanglementPairs(SafeDict):
# There only should be one instance of Hosts
__instance = None

@staticmethod
def get_instance():
if ProjectQBackend.EntanglementPairs.__instance is not None:
return ProjectQBackend.EntanglementPairs.__instance
else:
return ProjectQBackend.EntanglementPairs()

def __init__(self):
if ProjectQBackend.EntanglementPairs.__instance is not None:
raise Exception("Call get instance to get this class!")
ProjectQBackend.EntanglementPairs.__instance = self
SafeDict.__init__(self)

class Hosts(SafeDict):
# There only should be one instance of Hosts
__instance = None
Expand Down Expand Up @@ -102,63 +84,27 @@ def send_qubit_to(self, qubit, from_host_id, to_host_id):
"""
qubit.host = self._hosts.get_from_dict(to_host_id)

def create_EPR(self, host_a_id, host_b_id, q_id=None, block=False):
def create_EPR(self, host_id, q_id=None, block=False):
"""
Creates an EPR pair for two qubits and returns one of the qubits.
Creates an EPR pair for two qubits and returns both of the qubits.

Args:
host_a_id (String): ID of the first host who gets the EPR state.
host_b_id (String): ID of the second host who gets the EPR state.
host_id (String): ID of the host who creates the EPR state.
q_id (String): Optional id which both qubits should have.
block (bool): Determines if the created pair should be blocked or not.
Returns:
Returns a qubit. The qubit belongs to host a. To get the second
qubit of host b, the receive_epr function has to be called.
Returns both EPR qubits.
"""
q1 = self.create_qubit(host_a_id)
q2 = self.create_qubit(host_b_id)
q1 = self.create_qubit(host_id)
q2 = self.create_qubit(host_id)

projectq.ops.H | q1
projectq.ops.CNOT | (q1, q2)

host_a = self._hosts.get_from_dict(host_a_id)
host_b = self._hosts.get_from_dict(host_b_id)
qubit_b = Qubit(host_b, qubit=q2, q_id=q_id, blocked=block)
qubit = Qubit(host_a, qubit=q1, q_id=q_id, blocked=block)
self.store_ent_pair(host_a.host_id, host_b.host_id, qubit_b)
return qubit

def store_ent_pair(self, host_a, host_b, qubit):
key = host_a + ':' + host_b
ent_queue = self._entaglement_pairs.get_from_dict(key)

if ent_queue is not None:
ent_queue.put(qubit)
else:
ent_queue = Queue()
ent_queue.put(qubit)
self._entaglement_pairs.add_to_dict(key, ent_queue)

def receive_epr(self, host_id, sender_id, q_id=None, block=False):
"""
Called after create EPR in the receiver, to receive the other EPR pair.

Args:
host_id (String): ID of the first host who gets the EPR state.
sender_id (String): ID of the sender of the EPR pair.
q_id (String): Optional id which both qubits should have.
block (bool): Determines if the created pair should be blocked or not.
Returns:
Returns an EPR qubit with the other Host.
"""
key = sender_id + ':' + host_id
ent_queue = self._entaglement_pairs.get_from_dict(key)
if ent_queue is None:
raise Exception("Internal Error!")
qubit = ent_queue.get()
if q_id is not None and q_id != qubit.id:
raise ValueError("Qid doesn't match id!")
return qubit
host = self._hosts.get_from_dict(host_id)
qubit_b = Qubit(host, qubit=q2, q_id=q_id, blocked=block)
qubit = Qubit(host, qubit=q1, q_id=q_id, blocked=block)
return qubit, qubit_b

##########################
# Gate definitions #
Expand Down
Loading