Source code for SimulaQron.cqc.backend.cqcHeader

#
# 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 sys, logging

from struct import *

# Constant defining CQC version
CQC_VERSION=0

# Lengths of the headers in bytes
CQC_HDR_LENGTH=8		# Length of the CQC Header
CQC_CMD_HDR_LENGTH=4		# Length of a command header
CQC_CMD_XTRA_LENGTH=16		# Length of extra command information
CQC_NOTIFY_LENGTH=20		# Length of a notification send from the CQC upwards

# Constants defining the messages types
CQC_TP_HELLO=0			# Alive check
CQC_TP_COMMAND=1		# Execute a command list
CQC_TP_FACTORY=2 		# Start executing command list repeatedly
CQC_TP_EXPIRE=3			# Qubit has expired
CQC_TP_DONE=4			# Done with command
CQC_TP_RECV=5			# Received qubit
CQC_TP_EPR_OK=6			# Created EPR pair
CQC_TP_MEASOUT=7		# Measurement outcome
CQC_TP_GET_TIME=8		# Get creation time of qubit
CQC_TP_INF_TIME=9		# Return timinig information
CQC_TP_NEW_OK=10		# Created a new qubit

CQC_ERR_GENERAL=20 		# General purpose error (no details
CQC_ERR_NOQUBIT=21 		# No more qubits available
CQC_ERR_UNSUPP=22 		# No sequence not supported
CQC_ERR_TIMEOUT=23 		# Timeout

# Possible commands
CQC_CMD_I=0			# Identity (do nothing, wait one step)
CQC_CMD_NEW=1			# Ask for a new qubit
CQC_CMD_MEASURE=2		# Measure qubit
CQC_CMD_MEASURE_INPLACE=3	# Measure qubit inplace
CQC_CMD_RESET=4			# Reset qubit to |0>
CQC_CMD_SEND=5			# Send qubit to another node
CQC_CMD_RECV=6			# Ask to receive qubit
CQC_CMD_EPR=7			# Create EPR pair with the specified node
CQC_CMD_EPR_RECV=8		# Receive half of EPR pair created with other node

CQC_CMD_X=10			# Pauli X
CQC_CMD_Z=11			# Pauli Z
CQC_CMD_Y=12			# Pauli Y
CQC_CMD_T=13			# T Gate
CQC_CMD_ROT_X=14		# Rotation over angle around X in 2pi/256 increments
CQC_CMD_ROT_Y=15		# Rotation over angle around Y in 2pi/256 increments
CQC_CMD_ROT_Z=16		# Rotation over angle around Z in 2pi/256 increments
CQC_CMD_H=17			# Hadamard H
CQC_CMD_K=18			# K Gate - taking computational to Y eigenbasis

CQC_CMD_CNOT=20			# CNOT Gate with this as control
CQC_CMD_CPHASE=21		# CPHASE Gate with this as control

# Command options
CQC_OPT_NOTIFY=0x01		# Send a notification when cmd done
CQC_OPT_ACTION=0x02		# On if there are actions to execute when done
CQC_OPT_BLOCK=0x04		# Block until command is done

[docs]class CQCHeader: """ Definition of the general CQC header. """ def __init__(self, headerBytes = None): """ Initialize using values received from a packet. """ if headerBytes == None: self.is_set = False self.version = 0 self.tp = -1 self.app_id = 0 self.length = 0 else: self.unpack(headerBytes)
[docs] def setVals(self, version, tp, app_id, length): """ Set using given values. """ self.version = version self.tp = tp self.app_id = app_id self.length = length self.is_set = True
[docs] def pack(self): """ Pack data into packet format. For defnitions see cLib/cgc.h """ if not self.is_set: return(0) cqcH = pack("=BBHL",self.version, self.tp, self.app_id, self.length) return(cqcH)
[docs] def unpack(self, headerBytes): """ Unpack packet data. For definitions see cLib/cqc.h """ cqcH = unpack("=BBHL", headerBytes) self.version = cqcH[0] self.tp = cqcH[1] self.app_id = cqcH[2] self.length = cqcH[3] self.is_set = True
[docs] def printable(self): """ Produce a printable string for information purposes. """ if not self.is_set: return(" ") toPrint = "Version: " + str(self.version) + " " toPrint = toPrint + "Type: " + str(self.tp) + " " toPrint = toPrint + "App ID: " + str(self.app_id) return(toPrint)
[docs]class CQCCmdHeader: """ Header for a command instruction packet. """ def __init__(self, headerBytes = None): """ Initialize using values received from a packet, if available. """ self.notify = False self.block = False self.action = False if headerBytes == None: self.is_set = False self.qubit_id = 0 self.instr = 0 else: self.unpack(headerBytes)
[docs] def setVals(self, qubit_id, instr, notify, block, action): """ Set using given values. """ self.qubit_id = qubit_id self.instr = instr self.notify = notify self.block = block self.action = action self.is_set = True
[docs] def pack(self): """ Pack data into packet format. For defnitions see cLib/cgc.h """ if not self.is_set: return(0) opt = 0 if self.notify: opt = opt | CQC_OPT_NOTIFY if self.block: opt = opt | CQC_OPT_BLOCK if self.action: opt = opt | CQC_OPT_ACTION cmdH = pack("=HBB",self.qubit_id, self.instr, opt) return(cmdH)
[docs] def unpack(self, headerBytes): """ Unpack packet data. For definitions see cLib/cqc.h """ cmdH = unpack("=HBB", headerBytes) self.qubit_id = cmdH[0] self.instr = cmdH[1] if cmdH[2] & CQC_OPT_NOTIFY: self.notify = True if cmdH[2] & CQC_OPT_BLOCK: self.block = True if cmdH[2] & CQC_OPT_ACTION: self.action = True self.is_set = True
[docs] def printable(self): """ Produce a printable string for information purposes. """ if not self.is_set: return(" ") toPrint = "Qubit ID: " + str(self.qubit_id) + " " toPrint = toPrint + "Instruction: " + str(self.instr) + " " toPrint = toPrint + "Notify: " + str(self.notify) + " " toPrint = toPrint + "Block: " + str(self.block) + " " toPrint = toPrint + "Action: " + str(self.action) return(toPrint)
[docs]class CQCXtraHeader: """ Optional addtional cmd header information. Only relevant for certain commands. """ def __init__(self, headerBytes = None): """ Initialize using values received from a packet. """ if headerBytes == None: self.is_set = False self.qubit_id = 0 self.step = 0 self.remote_app_id = 0 self.remote_node = 0 self.remote_port = 0 self.cmdLength = 0 else: self.unpack(headerBytes)
[docs] def setVals(self, xtra_qubit_id, step, remote_app_id, remote_node, remote_port, cmdLength): """ Set using given values. """ self.qubit_id = xtra_qubit_id self.step = step self.remote_app_id = remote_app_id self.remote_node = remote_node self.remote_port = remote_port self.cmdLength = cmdLength self.is_set = True
[docs] def pack(self): """ Pack data into packet form. For definitions see cLib/cqc.h """ if not self.is_set: return(0) xtraH = pack("=HHLLHBB", self.qubit_id, self.remote_app_id, self.remote_node, self.cmdLength, self.remote_port, self.step, 0) return(xtraH)
[docs] def unpack(self, headerBytes): """ Unpack packet data. For defnitions see cLib/cqc.h """ xtraH = unpack("=HHLLHBB", headerBytes) self.qubit_id = xtraH[0] self.remote_app_id = xtraH[1] self.remote_node = xtraH[2] self.cmdLength = xtraH[3] self.remote_port = xtraH[4] self.step = xtraH[5] self.is_set = True
[docs] def printable(self): """ Produce a printable string for information purposes. """ if not self.is_set: return(" ") toPrint = "Xtra Qubit: " + str(self.qubit_id) + " " toPrint = toPrint + "Angle Step: " + str(self.step) + " " toPrint = toPrint + "Remote App ID: " + str(self.remote_app_id) + " " toPrint = toPrint + "Remote Node: " + str(self.remote_node) + " " toPrint = toPrint + "Remote Port: " + str(self.remote_port) + " " toPrint = toPrint + "Command Length: " + str(self.cmdLength) return(toPrint)
[docs]class CQCNotifyHeader: """ Header used to specify notification details. """ def __init__(self, headerBytes = None): """ Initialize from packet data. """ if headerBytes == None: self.is_set = False self.qubit_id = 0 self.outcome = 0 self.remote_app_id = 0 self.remote_node = 0 self.remote_port = 0 self.datetime = 0 else: self.unpack(headerBytes)
[docs] def setVals(self, qubit_id, outcome, remote_app_id, remote_node, remote_port, datetime): """ Set using given values. """ self.qubit_id = qubit_id self.outcome = outcome self.remote_app_id = remote_app_id self.remote_node = remote_node self.remote_port = remote_port self.datetime = datetime self.is_set=True
[docs] def pack(self): """ Pack data into packet form. For definitions see cLib/cqc.h """ if not self.is_set: return 0 xtraH = pack("=HHLQHBB", self.qubit_id, self.remote_app_id, self.remote_node, self.datetime, self.remote_port, self.outcome, 0) return(xtraH)
[docs] def unpack(self, headerBytes): """ Unpack packet data. For defnitions see cLib/cqc.h """ xtraH = unpack("=HHLQHBB", headerBytes) self.qubit_id = xtraH[0] self.remote_app_id = xtraH[1] self.remote_node = xtraH[2] self.datetime = xtraH[3] self.remote_port = xtraH[4] self.outcome = xtraH[5] self.is_set = True
[docs] def printable(self): """ Produce a printable string for information purposes. """ if not self.is_set: return(" ") toPrint = "Qubit ID: " + str(self.qubit_id) + " " toPrint = toPrint + "Outcome: " + str(self.outcome) + " " toPrint = toPrint + "Remote App ID: " + str(self.remote_app_id) + " " toPrint = toPrint + "Remote Node: " + str(self.remote_node) + " " toPrint = toPrint + "Remote Port: " + str(self.remote_port) + " " toPrint = toPrint + "Datetime: " + str(self.datetime) return(toPrint)