Module dqcsim.common

Contains wrappers for various DQCsim API handles.

Expand source code
"""Contains wrappers for various DQCsim API handles."""

__all__ = [ #@
    'ArbData',
    'ArbCmd',
    'ArbCmdQueue',
    'Handle',
    'Measurement',
    'MeasurementSet',
    'QubitSet',
    'Loglevel',
]

__pdoc__ = { #@
    # Don't output documentation for objects that the user shouldn't need.
    'cq': False,
    'ArbCmdQueue': False,
    'handle': False,
    'Handle': False,
    'mset': False,
    'MeasurementSet': False,
    'qbset': False,
    'QubitSet': False,

    # Override documentation for the re-exports.
    'ArbData': "Re-export of `dqcsim.common.arb.ArbData`.",
    'ArbCmd': "Re-export of `dqcsim.common.cmd.ArbCmd`.",
    'Measurement': "Re-export of `dqcsim.common.meas.Measurement`.",
}

from enum import IntEnum
import dqcsim._dqcsim as raw

from dqcsim.common.arb import ArbData
from dqcsim.common.cmd import ArbCmd
from dqcsim.common.cq import ArbCmdQueue
from dqcsim.common.handle import Handle
from dqcsim.common.meas import Measurement
from dqcsim.common.mset import MeasurementSet
from dqcsim.common.qbset import QubitSet

class Loglevel(IntEnum):
    """Enumeration of the loglevels available in DQCsim."""

    TRACE = raw.DQCS_LOG_TRACE
    DEBUG = raw.DQCS_LOG_DEBUG
    INFO = raw.DQCS_LOG_INFO
    NOTE = raw.DQCS_LOG_NOTE
    WARN = raw.DQCS_LOG_WARN
    ERROR = raw.DQCS_LOG_ERROR
    FATAL = raw.DQCS_LOG_FATAL
    OFF = raw.DQCS_LOG_OFF

Sub-modules

dqcsim.common.arb

Contains a class wrapper for ArbData objects.

dqcsim.common.cmd

Contains a class wrapper for ArbCmd objects.

dqcsim.common.meas

Contains a class wrapper for Measurement objects.

Classes

class ArbCmd (*args, **kwargs)

Re-export of ArbCmd.

Expand source code
class ArbCmd(ArbData):
    """Represents an ArbCmd object.

    ArbData objects are used to transfer user-specified instructions from one
    DQCsim plugin to another. They consist of two identifying strings and an
    ArbData argument. In Python, the contained ArbData argument is represented
    using subclassing (so all ArbData operations also work on an ArbCmd).

    The two identifying strings are called the interface identifier and the
    operation identifier. Both strings must match exactly (case-sensitive) when
    matching an incoming ArbCmd against a handler. The difference between the
    two is that if the interface identifier is unrecognized the ArbCmd should
    be treated as no-op, whereas an error should be raised when the interface
    identifier is matched but the operation identifier is not.
    """

    def __init__(self, *args, **kwargs):
        """Constructs an ArbCmd object.

        The first two positional arguments are the interface identifier and the
        operation identifier. They must be valid identifiers, i.e. matching the
        regex /[a-zA-Z_0-9]+/. The remaining positional arguments and the
        keyword arguments are used to construct the `ArbData` argument.
        Alternatively, another `ArbCmd` object can be specified as the sole
        argument to make a copy.
        """
        super().__init__()
        if len(args) == 1 and not kwargs and isinstance(args[0], ArbCmd):
            super().__init__(args[0])
            self._iface = args[0]._iface
            self._oper = args[0]._oper
        elif len(args) >= 2:
            iface, oper, *args = args
            iface = str(iface)
            if not _ident_re.match(iface):
                raise ValueError('iface is not a valid identifier: {!r}'.format(iface))
            oper = str(oper)
            if not _ident_re.match(oper):
                raise ValueError('oper is not a valid identifier: {!r}'.format(oper))
            super().__init__(*args, **kwargs)
            self._iface = iface
            self._oper = oper
        else:
            raise TypeError('Invalid arguments passed to ArbCmd constructor')

    @property
    def iface(self): #@
        """The interface identifier."""
        return self._iface

    @property
    def oper(self): #@
        """The operation identifier."""
        return self._oper

    def __eq__(self, other):
        if isinstance(other, ArbCmd):
            return super().__eq__(other) and self._iface == other._iface and self._oper == other._oper
        return False

    @classmethod
    def _from_raw(cls, handle): #@
        """Constructs an ArbCmd object from a raw API handle."""
        arg = ArbData._from_raw(handle)
        with handle as hndl:
            cmd = ArbCmd(raw.dqcs_cmd_iface_get(hndl), raw.dqcs_cmd_oper_get(hndl))
        cmd._args = arg._args
        cmd._json = arg._json
        return cmd

    def _to_raw(self):
        """Makes an API handle for this ArbCmd object."""
        handle = Handle(raw.dqcs_cmd_new(self._iface, self._oper))
        super()._to_raw(handle)
        return handle

    def __repr__(self):
        e = [repr(self._iface), repr(self._oper)]
        for arg in self._args:
            e.append(repr(arg))
        for key, value in sorted(self._json.items()):
            e.append("{!s}={!r}".format(key, value))
        return "ArbCmd({})".format(', '.join(e))

    __str__ = __repr__

Ancestors

Instance variables

var iface

The interface identifier.

Expand source code
@property
def iface(self): #@
    """The interface identifier."""
    return self._iface
var oper

The operation identifier.

Expand source code
@property
def oper(self): #@
    """The operation identifier."""
    return self._oper

Inherited members

class ArbData (*args, **kwargs)

Re-export of ArbData.

Expand source code
class ArbData(object):
    """Represents an ArbData object.

    ArbData objects are used to transfer user-specified data from one DQCsim
    plugin to another. They are composed of a CBOR-like object (superset of
    JSON) and a list of binary strings. The Python interface to DQCsim wraps
    ArbData objects in a class that behaves like a list and a dict at the same
    time; the list containing the binary strings and the dict containing the
    toplevel JSON/CBOR object entries. The class enforces that the binary
    string list entries implement Python's buffer protocol (bytes, bytearray,
    etc.) and that the JSON/CBOR entries are serializable as such using the
    cbor library.
    """

    def __init__(self, *args, **kwargs):
        """Constructs an ArbData object.

        The positional arguments are used to construct the binary argument
        list. They must therefore be binary strings or buffers. The keyword
        arguments are used to construct the JSON data. For instance:

            ArbData(b"test1", b"test2", answer=42)

        constructs an ArbData object with JSON `{"answer": 42}` and arguments
        `[b"test1", b"test2"]`. You can also pass an `ArbData` object as the
        sole argument, in which case a copy will be made.
        """
        super().__init__()
        if len(args) == 1 and not kwargs and isinstance(args[0], ArbData):
            self._args = copy.deepcopy(args[0]._args)
            self._json = copy.deepcopy(args[0]._json)
        else:
            for arg in args:
                memoryview(arg)
            self._args = list(args)
            _check_json(kwargs)
            self._json = kwargs

    def __bool__(self):
        """Returns whether there is non-default data in this ArbData object."""
        return bool(self._args) or bool(self._json)

    def __len__(self):
        """Returns the number of binary string arguments."""
        return len(self._args)

    def __getitem__(self, key):
        """Returns the binary string at the given index if key is numeric, or
        the JSON sub-object associated with the given key if key is a
        string."""
        if isinstance(key, str):
            return self._json[key]
        else:
            return self._args[key]

    def __setitem__(self, key, value):
        """Sets the binary string at the given index if key is numeric, or
        sets the JSON sub-object associated with the given key if key is a
        string."""
        if isinstance(key, str):
            _check_json(value)
            self._json[key] = value
        else:
            memoryview(value)
            self._args[key] = value

    def __delitem__(self, key):
        """Deletes the binary string at the given index if key is numeric, or
        deletes the JSON sub-object associated with the given key if key is a
        string."""
        if isinstance(key, str):
            del self._json[key]
        else:
            del self._args[key]

    def __contains__(self, item):
        """If key is a string, tests existence of the key in the toplevel JSON
        object. If it is a binary string, tests if it is one of the binary
        string arguments."""
        if isinstance(item, str):
            return item in self._json
        else:
            return item in self._args

    def __iter__(self):
        """Iterates over the binary arguments."""
        for arg in self._args:
            yield arg

    def append(self, value):
        """Appends a binary string to the list."""
        memoryview(value)
        self._args.append(value)

    def insert(self, index, value):
        """Inserts a binary string into the list."""
        memoryview(value)
        self._args.insert(index, value)

    def extend(self, it):
        """Extends the binary strings with the given iterator."""
        for value in it:
            self.append(value)

    def keys(self):
        """Iterates over the JSON object entry keys."""
        return self._json.keys()

    def values(self):
        """Iterates over the JSON object values."""
        return self._json.values()

    def items(self):
        """Iterates over the JSON object items."""
        return self._json.items()

    def clear_args(self):
        """Clears the binary argument list."""
        self._args = []

    def clear_json(self):
        """Clears the JSON data."""
        self._json = {}

    def clear(self):
        """Resets the ArbData object."""
        self.clear_args()
        self.clear_json()

    def __eq__(self, other):
        if isinstance(other, ArbData):
            return self._args == other._args and self._json == other._json
        return False

    @classmethod
    def _from_raw(cls, handle): #@
        """Constructs an ArbData object from a raw API handle."""
        # Load CBOR.
        with handle as hndl:
            cb = bytearray(256)
            cbl = raw.dqcs_arb_cbor_get(hndl, cb)
            if cbl > 256:
                cb = bytearray(cbl)
                raw.dqcs_arb_cbor_get(hndl, cb)
            kwargs = cbor.loads(cb)

            # Load binary arguments.
            args = []
            for i in range(raw.dqcs_arb_len(hndl)):
                arg = bytearray(256)
                argl = raw.dqcs_arb_get_raw(hndl, i, arg)
                if argl > 256:
                    arg = bytearray(argl)
                    raw.dqcs_arb_get_raw(hndl, i, arg)
                args.append(bytes(arg[:argl]))

        return ArbData(*args, **kwargs)

    def _to_raw(self, handle=None):
        """Makes an API handle for this ArbData object."""
        if handle is None:
            handle = Handle(raw.dqcs_arb_new())
        else:
            raw.dqcs_arb_clear(int(handle))
        with handle as hndl:
            raw.dqcs_arb_cbor_set(hndl, cbor.dumps(self._json))
            for arg in self._args:
                raw.dqcs_arb_push_raw(hndl, arg)
        return handle

    def __repr__(self):
        e = []
        for arg in self._args:
            e.append(repr(arg))
        for key, value in sorted(self._json.items()):
            e.append("{!s}={!r}".format(key, value))
        return "ArbData({})".format(', '.join(e))

    __str__ = __repr__

Subclasses

Methods

def append(self, value)

Appends a binary string to the list.

Expand source code
def append(self, value):
    """Appends a binary string to the list."""
    memoryview(value)
    self._args.append(value)
def clear(self)

Resets the ArbData object.

Expand source code
def clear(self):
    """Resets the ArbData object."""
    self.clear_args()
    self.clear_json()
def clear_args(self)

Clears the binary argument list.

Expand source code
def clear_args(self):
    """Clears the binary argument list."""
    self._args = []
def clear_json(self)

Clears the JSON data.

Expand source code
def clear_json(self):
    """Clears the JSON data."""
    self._json = {}
def extend(self, it)

Extends the binary strings with the given iterator.

Expand source code
def extend(self, it):
    """Extends the binary strings with the given iterator."""
    for value in it:
        self.append(value)
def insert(self, index, value)

Inserts a binary string into the list.

Expand source code
def insert(self, index, value):
    """Inserts a binary string into the list."""
    memoryview(value)
    self._args.insert(index, value)
def items(self)

Iterates over the JSON object items.

Expand source code
def items(self):
    """Iterates over the JSON object items."""
    return self._json.items()
def keys(self)

Iterates over the JSON object entry keys.

Expand source code
def keys(self):
    """Iterates over the JSON object entry keys."""
    return self._json.keys()
def values(self)

Iterates over the JSON object values.

Expand source code
def values(self):
    """Iterates over the JSON object values."""
    return self._json.values()
class Loglevel (value, names=None, *, module=None, qualname=None, type=None, start=1)

Enumeration of the loglevels available in DQCsim.

Expand source code
class Loglevel(IntEnum):
    """Enumeration of the loglevels available in DQCsim."""

    TRACE = raw.DQCS_LOG_TRACE
    DEBUG = raw.DQCS_LOG_DEBUG
    INFO = raw.DQCS_LOG_INFO
    NOTE = raw.DQCS_LOG_NOTE
    WARN = raw.DQCS_LOG_WARN
    ERROR = raw.DQCS_LOG_ERROR
    FATAL = raw.DQCS_LOG_FATAL
    OFF = raw.DQCS_LOG_OFF

Ancestors

  • enum.IntEnum
  • builtins.int
  • enum.Enum

Class variables

var DEBUG
var ERROR
var FATAL
var INFO
var NOTE
var OFF
var TRACE
var WARN
class Measurement (qubit, value, *args, **kwargs)

Re-export of Measurement.

Expand source code
class Measurement(ArbData):
    """Represents a measurement object.

    Measurement objects consist of an integer referencing the qubit that was
    measured and a measurement value. The value can be 0, 1, or None
    (= undefined).

    Measurements also have an attached `ArbData` object. This is modelled in
    Python through inheritance.
    """

    def __init__(self, qubit, value, *args, **kwargs):
        """Constructs a Measurement object.

        The first two positional arguments are the qubit reference and the
        measurement value. The remaining positional arguments and the keyword
        arguments are used to construct the attached `ArbData` object.
        """
        super().__init__(*args, **kwargs)
        self.qubit = qubit
        self.value = value

    @property
    def qubit(self): #@
        """The qubit associated with this measurement."""
        return self.__qubit

    @qubit.setter
    def qubit(self, qubit): #@
        qubit = int(qubit)
        if qubit < 1:
            raise ValueError('invalid qubit reference: {!r}'.format(qubit))
        self.__qubit = qubit

    @property
    def value(self): #@
        """The measurement value; either 0, 1, or None (= undefined)."""
        return self.__value

    @value.setter
    def value(self, value): #@
        if value is not None:
            value = int(bool(value))
        self.__value = value

    def __eq__(self, other):
        if isinstance(other, Measurement):
            return super().__eq__(other) and self.qubit == other.qubit and self.value == other.value
        return False

    @classmethod
    def _from_raw(cls, handle): #@
        """Constructs a measurement object from a raw API handle."""
        arg = ArbData._from_raw(handle)
        with handle as hndl:
            value = raw.dqcs_meas_value_get(hndl)
            if value == raw.DQCS_MEAS_UNDEFINED:
                value = None
            elif value == raw.DQCS_MEAS_ZERO:
                value = 0
            elif value == raw.DQCS_MEAS_ONE:
                value = 1
            else:
                assert(False)
            meas = Measurement(raw.dqcs_meas_qubit_get(hndl), value)
        meas._args = arg._args
        meas._json = arg._json
        return meas

    def _to_raw(self):
        """Makes an API handle for this measurement object."""
        value = self.value
        if value is None:
            value = raw.DQCS_MEAS_UNDEFINED
        elif value == 0:
            value = raw.DQCS_MEAS_ZERO
        elif value == 1:
            value = raw.DQCS_MEAS_ONE
        else:
            assert(False)
        handle = Handle(raw.dqcs_meas_new(self.qubit, value))
        super()._to_raw(handle)
        return handle

    def __repr__(self):
        e = [repr(self.qubit), repr(self.value)]
        for arg in self._args:
            e.append(repr(arg))
        for key, value in sorted(self._json.items()):
            e.append("{!s}={!r}".format(key, value))
        return "Measurement({})".format(', '.join(e))

    __str__ = __repr__

Ancestors

Instance variables

var qubit

The qubit associated with this measurement.

Expand source code
@property
def qubit(self): #@
    """The qubit associated with this measurement."""
    return self.__qubit
var value

The measurement value; either 0, 1, or None (= undefined).

Expand source code
@property
def value(self): #@
    """The measurement value; either 0, 1, or None (= undefined)."""
    return self.__value

Inherited members