Source code for cqc.entInfoHeader
#
# Copyright (c) 2017, Stephanie Wehner and Axel Dahlberg
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed by Stephanie Wehner, QuTech.
# 4. Neither the name of the QuTech organization nor the
# names of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ''AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES
# LOSS OF USE, DATA, OR PROFITS OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import logging
import struct
import bitstring
from cqc.cqcHeader import Header
# Lengths of the headers in bytes
ENT_INFO_LENGTH = 40 # Length of a entanglement information header
ENT_INFO_CREATE_KEEP_LENGTH = 32 # Length of a entanglement information header (for create and keep)
ENT_INFO_MEAS_DIRECT_LENGTH = 28 # Length of a entanglement information header (for measure directly)
ENT_INFO_TP_CREATE_KEEP = 1 # Type of message when entanglement is kept
ENT_INFO_TP_MEAS_DIRECT = 2 # Type of message when entanglement is measured directly (for classical correlations)
[docs]class EntInfoHeader(Header):
"""
Header for a entanglement information packet. Fo
"""
HDR_LENGTH = ENT_INFO_LENGTH
packaging_format = "!LHHLHHLQQHBB"
[docs] def __init__(self, headerBytes=None):
"""
Initialize using values received from a packet, if available.
"""
super().__init__(headerBytes)
if headerBytes is None:
self.node_A = 0
self.port_A = 0
self.app_id_A = 0
self.node_B = 0
self.port_B = 0
self.app_id_B = 0
self.id_AB = 0
self.timestamp = 0
self.ToG = 0
self.goodness = 0
self.DF = 0
self.is_set = False
else:
self.unpack(headerBytes)
self.is_set = True
def _setVals(self, node_A=0, port_A=0, app_id_A=0, node_B=0, port_B=0, app_id_B=0, id_AB=0, timestamp=0, ToG=0,
goodness=0, DF=0):
"""
Set using given values.
"""
self.type = type
self.node_A = node_A
self.port_A = port_A
self.app_id_A = app_id_A
self.node_B = node_B
self.port_B = port_B
self.app_id_B = app_id_B
self.id_AB = id_AB
self.timestamp = timestamp
self.ToG = ToG
self.goodness = goodness
self.DF = DF
self.is_set = True
def _pack(self):
"""
Pack data into packet format. For defnitions see cLib/cgc.h
"""
ent_info = struct.pack(
self.packaging_format,
self.node_A,
self.port_A,
self.app_id_A,
self.node_B,
self.port_B,
self.app_id_B,
self.id_AB,
self.timestamp,
self.ToG,
self.goodness,
self.DF,
0,
)
return ent_info
def _unpack(self, headerBytes):
"""
Unpack packet data. For definitions see cLib/cqc.h
"""
ent_info = struct.unpack(self.packaging_format, headerBytes)
self.node_A = ent_info[0]
self.port_A = ent_info[1]
self.app_id_A = ent_info[2]
self.node_B = ent_info[3]
self.port_B = ent_info[4]
self.app_id_B = ent_info[5]
self.id_AB = ent_info[6]
self.timestamp = ent_info[7]
self.ToG = ent_info[8]
self.goodness = ent_info[9]
self.DF = ent_info[10]
def _printable(self):
"""
Produce a printable string for information purposes.
"""
toPrint = "A: ({}, {}, {})".format(self.node_A, self.port_A, self.app_id_A) + " "
toPrint += "B: ({}, {}, {})".format(self.node_B, self.port_B, self.app_id_B) + " "
toPrint += "Entanglement ID: " + str(self.id_AB) + " "
toPrint += "Timestamp: " + str(self.timestamp) + " "
toPrint += "Time of Goodness: " + str(self.ToG) + " "
toPrint += "Goodness: " + str(self.goodness) + " "
toPrint += "Directionality Flag: " + str(self.DF)
return toPrint
[docs] def switch_nodes(self):
"""
Switches the ip and port of the nodes and flips the directionality flag.
Used to give correct message to both nodes.
"""
# Get current info
node_A = self.node_A
port_A = self.port_A
app_id_A = self.app_id_A
node_B = self.node_B
port_B = self.port_B
app_id_B = self.app_id_B
DF = self.DF
# Update
self.node_A = node_B
self.port_A = port_B
self.app_id_A = app_id_B
self.node_B = node_A
self.port_B = port_A
self.app_id_B = app_id_A
if DF == 0:
self.DF = 0
elif DF == 1:
self.DF = 2
elif DF == 2:
self.DF = 1
else:
logging.warning("Unknown directionality flag")
self.DF = DF
[docs]class EntInfoCreateKeepHeader(Header):
"""
Header for a entanglement information packet, where entanglement is kept after generation
"""
type = ENT_INFO_TP_CREATE_KEEP
package_format = (
"uint:4=type, "
"uint:16=mhp_seq, "
"uint:1=DF, "
"uint:11=0, "
"uint:32=ip_A, "
"uint:32=ip_B, "
"uint:16=port_A, "
"uint:16=port_B, "
"float:32=t_create, "
"float:32=t_goodness, "
"float:32=goodness, "
"uint:32=create_id"
)
HDR_LENGTH = ENT_INFO_CREATE_KEEP_LENGTH
def _setVals(self, ip_A=0, port_A=0, ip_B=0, port_B=0, mhp_seq=0, t_create=0.0, t_goodness=0.0, goodness=0.0, DF=0,
create_id=0):
"""
Set using given values.
"""
self.ip_A = ip_A
self.port_A = port_A
self.ip_B = ip_B
self.port_B = port_B
self.mhp_seq = mhp_seq
self.t_create = t_create
self.t_goodness = t_goodness
self.goodness = goodness
self.DF = DF
self.create_id = create_id
def _pack(self):
"""
Pack data into packet format. For defnitions see cLib/cgc.h
"""
to_pack = {
"type": self.type,
"ip_A": self.ip_A,
"port_A": self.port_A,
"ip_B": self.ip_B,
"port_B": self.port_B,
"mhp_seq": self.mhp_seq,
"t_create": self.t_create,
"t_goodness": self.t_goodness,
"goodness": self.goodness,
"DF": self.DF,
"create_id": self.create_id,
}
ent_info_Bitstring = bitstring.pack(self.package_format, **to_pack)
ent_info = ent_info_Bitstring.tobytes()
return ent_info
def _unpack(self, headerBytes):
"""
Unpack packet data. For definitions see cLib/cqc.h
"""
ent_info_Bitstring = bitstring.BitString(headerBytes)
type = ent_info_Bitstring.read("uint:4")
if type != self.type:
raise ValueError("Not an OK of type create-keep")
ent_info = ent_info_Bitstring.unpack(self.package_format)
self.mhp_seq = ent_info[1]
self.DF = ent_info[2]
self.ip_A = ent_info[4]
self.ip_B = ent_info[5]
self.port_A = ent_info[6]
self.port_B = ent_info[7]
self.t_create = ent_info[8]
self.t_goodness = ent_info[9]
self.goodness = ent_info[10]
self.create_id = ent_info[11]
def _printable(self):
"""
Produce a printable string for information purposes.
"""
toPrint = "Create and Keep OK with createID={}".format(self.create_id) + " "
toPrint += "A: ({}, {})".format(self.ip_A, self.port_A) + " "
toPrint += "B: ({}, {})".format(self.ip_B, self.port_B) + " "
toPrint += "MHP seq.: " + str(self.mhp_seq) + " "
toPrint += "Time of creation: " + str(self.t_create) + " "
toPrint += "Time of Goodness: " + str(self.t_goodness) + " "
toPrint += "Goodness: " + str(self.goodness) + " "
toPrint += "Directionality Flag: " + str(self.DF)
return toPrint
[docs] def switch_nodes(self):
"""
Switches the ip and port of the nodes and flips the directionality flag.
Used to give correct message to both nodes.
"""
# Get current info
ip_A = self.ip_A
port_A = self.port_A
ip_B = self.ip_B
port_B = self.port_B
DF = self.DF
# Update
self.ip_A = ip_B
self.port_A = port_B
self.ip_B = ip_A
self.port_B = port_A
if DF == 0:
self.DF = 0
elif DF == 1:
self.DF = 2
elif DF == 2:
self.DF = 1
else:
logging.warning("Unknown directionality flag")
self.DF = DF
[docs]class EntInfoMeasDirectHeader(Header):
"""
Header for a entanglement information packet, where communication qubit is measured directly after emission.
"""
type = ENT_INFO_TP_MEAS_DIRECT
package_format = (
"uint:4=type, "
"uint:16=mhp_seq, "
"uint:1=DF, "
"uint:1=meas_out, "
"uint:2=basis, "
"uint:8=0, "
"uint:32=ip_A, "
"uint:32=ip_B, "
"uint:16=port_A, "
"uint:16=port_B, "
"float:32=t_create, "
"float:32=goodness, "
"uint:32=create_id"
)
HDR_LENGTH = ENT_INFO_MEAS_DIRECT_LENGTH
def _setVals(self, ip_A=0, port_A=0, ip_B=0, port_B=0, mhp_seq=0, meas_out=0, basis=0, t_create=0.0, goodness=0.0,
DF=0, create_id=0):
"""
Set using given values.
"""
self.ip_A = ip_A
self.port_A = port_A
self.ip_B = ip_B
self.port_B = port_B
self.mhp_seq = mhp_seq
self.meas_out = meas_out
self.basis = basis
self.t_create = t_create
self.goodness = goodness
self.DF = DF
self.create_id = create_id
def _pack(self):
"""
Pack data into packet format. For defnitions see cLib/cgc.h
"""
to_pack = {
"type": self.type,
"ip_A": self.ip_A,
"port_A": self.port_A,
"ip_B": self.ip_B,
"port_B": self.port_B,
"mhp_seq": self.mhp_seq,
"meas_out": self.meas_out,
"basis": self.basis,
"t_create": self.t_create,
"goodness": self.goodness,
"DF": self.DF,
"create_id": self.create_id,
}
ent_info_Bitstring = bitstring.pack(self.package_format, **to_pack)
ent_info = ent_info_Bitstring.tobytes()
return ent_info
def _unpack(self, headerBytes):
"""
Unpack packet data. For definitions see cLib/cqc.h
"""
ent_info_Bitstring = bitstring.BitString(headerBytes)
type = ent_info_Bitstring.read("uint:4")
if type != self.type:
raise ValueError("Not an OK of type measure-directly")
ent_info = ent_info_Bitstring.unpack(self.package_format)
self.mhp_seq = ent_info[1]
self.DF = ent_info[2]
self.meas_out = ent_info[3]
self.basis = ent_info[4]
self.ip_A = ent_info[6]
self.ip_B = ent_info[7]
self.port_A = ent_info[8]
self.port_B = ent_info[9]
self.t_create = ent_info[10]
self.goodness = ent_info[11]
self.create_id = ent_info[12]
def _printable(self):
"""
Produce a printable string for information purposes.
"""
toPrint = "Measure Direclty OK with createID={}".format(self.create_id) + " "
toPrint += "A: ({}, {})".format(self.ip_A, self.port_A) + " "
toPrint += "B: ({}, {})".format(self.ip_B, self.port_B) + " "
toPrint += "MHP seq.: " + str(self.mhp_seq) + " "
toPrint += "Measurement outcome: " + str(self.meas_out) + " "
toPrint += "Measurement basis: " + str(self.basis) + " "
toPrint += "Time of creation: " + str(self.t_create) + " "
toPrint += "Goodness: " + str(self.goodness) + " "
toPrint += "Directionality Flag: " + str(self.DF)
return toPrint
[docs] def switch_nodes(self):
"""
Switches the ip and port of the nodes and flips the directionality flag.
Used to give correct message to both nodes.
"""
# Get current info
ip_A = self.ip_A
port_A = self.port_A
ip_B = self.ip_B
port_B = self.port_B
DF = self.DF
# Update
self.ip_A = ip_B
self.port_A = port_B
self.ip_B = ip_A
self.port_B = port_A
if DF == 0:
self.DF = 0
elif DF == 1:
self.DF = 2
elif DF == 2:
self.DF = 1
else:
logging.warning("Unknown directionality flag")
self.DF = DF