Quantum Python Module

The Quantum module provides a directed acyclic processing network framework. This includes data structures, multi-threaded task scheduling for traversals, an observer pattern for event signaling, and a kernel object that manages the plugin system as well as the scheduler. The plugin system allows for the extension of cell functionality so new cell types can easily be written and dropped into the system to accomplish new tasks.

To use the Quantum Python Module:

Using Quantum Module
>>> import Quantum
class Quantum.Observe(subject, action)

An Observe object can register itself with any observable subject that inherits from QuObservable. The object will be notified whenever the observed subject has its py_notify() function called. The Observe object can be declared as a member in your class and initialized with the appropriate parameters to define the action executed when observation of a QuEvent occurs.

Parameters:
  • subject (QuObservable) – The object to observe.
  • action (callable) – The function to execute when an event occurs.
update(event)

Internal. This function is triggered by the event handling system. It calls the user-defined action function that was created at initialization.

Parameters:event (QuEvent) – An event object.
class Quantum.QuCell(cellname, cell=None)

This represents the underlying C++ cell object. It exposes the C++ cell functions such as process() to the Python environment. In this way, calculations happen in C++ but can be controlled from Python.

Parameters:
  • cellname (string) – The unique name of a cell that has been registered in the kernel. Available cell types are supplied by cell plugins.
  • cell (QuCell) – Optional. A reference to an existing cell.
Variables:
  • pid – The id of the most recent process run. Ids are determined by the Scheduler.
  • id – The unique cell id. Does not persist between app instances. This is regenerated every time the app is restarted. In most cases, it will have the same value as the last time it was generated but this is not guaranteed, therefore, do not write any scripts which depend on this value.
  • categories – A list of arbitrary category strings ordered by tree depth with each successive list item being one step deeper in the tree. It represents a single path down the tree, whereas the tree itself could have many branches. The categories list locates the cell within an arbitrarily complex tree. Just like the breadcrumb trail in a webpage.
  • in_keys – A list of input socket keys. Use it just like keys to a Dict
  • out_keys – A list of output socket keys. Used like Dict keys.
  • param_keys – A list of parameter socket keys. Used like Dict keys.
  • meta_keys – A list of metadata socket keys. Used like Dict keys.
  • inputs – A collection of input sockets indexed by in_keys.
  • outputs – A collection of output sockets indexed by out_keys.
  • parameters – A collection of parameter sockets indexed by param_keys.
  • metadata – A collection of metadata sockets indexed by meta_keys.
  • name – The name of the cell. You can assign a value and it will persist between application instances.
  • processed – Indicates if the cell has been processed. If false, the cell will process at next available opportunity.
  • type – The cell type
  • timeit – A switch to control the built-in process timer, which can be used to time the number of microseconds elapsed during process execution.
  • us – The number of microseconds it took to run the process. This is only calculated if enabled through the timeit property.
  • countit – A switch to control the built-in call counter, which can be used to count the number of times the cell has been executed.
  • count – The number of times the cell’s process function has been executed. Will only calculate if countit is True.
  • ack – A setting that determines if cell processes are re-processed when no inputs have changed. If set to True, then the cell recognizes that it does not need to reprocess when no inputs have changed. If set to False, then there is no acknowledgement of processing and the cell will always attempt to re-run the process call. This may be useful for functions such as print where the cell should always print whether or not the inputs have changed.
  • short_doc – A string describing the cell. Can be overwritten by to provide further detail on a particular cell instance.
  • return_msg – A status message that is set when a cell is executed.
  • threadsafe – Cells can self-report whether or not they are safe to run in threads. If not implemented, Quantum will assume they are not threadsafe. If non-threadsafe cells exist in a circuit, Quantum will spawn another process to execute the circuit so if a segmentation fault occurs, it will not crash the app.
activate()

Call the cell’s C++ activate method.

configure()

Call the cell’s C++ configuration script.

deactivate()

Call the cell’s C++ deactivate method.

process(id=-1)

Call the cell’s C++ process method.

Parameters:id (Integer) – Optional. Represents the token_id, which is determined by a scheduler.
reset()

Call the cell’s C++ reset method.

start()

Call the cell’s C++ start method.

stop()

Call the cell’s C++ stop method.

class Quantum.QuCellSocket

A container to hold any type of variable.

Variables:
  • type_name – The underlying C++ data type.
  • doc – Allows you to set and get documentation for particular socket instances. So each socket can have a unique doc.
  • value – The value held by the QuCellSocket.
  • token_id – An integer used by the scheduler to determine when a cell is ready for process execution. In order for execution to occur, the token_id of all input sockets must match. Otherwise, the scheduler will defer processing until the condition is met.
  • required – This is used by the parent cell to determine if a process execution can proceed without having a value in the socket.
  • supplied – This is used by the parent cell to determine if a value has been supplied to the socket.
  • graph_supplied – This is also used by the parent cell to determine if a socket has a value but the distinction here is that it has been supplied through a circuit calculation as opposed to user input.
  • internal_use – This lets the parent cell know whether or not a socket should be recieving values through circuit calculation rather than user input.
  • is_new – This tells the parent cell whether or not the value has been previously used in a process execution. It is primarily for optimizing calculations. If none of the sockets have new values, then there is no reason to recalculate the output sockets so subsequent calls to process() should not actually create any processing load.

Note

<< and >> are overloaded operators which insert and extract values from the QuCellSocket respectively. When a QuCellSocket is first instanced, it can assume any type. Once you assign a value, it takes on the type definition of whatever you assigned and you cannot change its type from that point on. Example:

>>> from Quantum import QuCellSocket
>>> a = QuCellSocket()  # a can take any type
>>> a << "Hello!"  # after assignment, a can only take strings
Hello!
>>> a << 123  # this will result in a TypeError
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "Quantum.pyx", line 569, in Quantum.QuCellSocket.__lshift__ (Quantum.cpp:7171)
  File "Quantum.pyx", line 563, in Quantum.QuCellSocket.lshift (Quantum.cpp:7087)
TypeError: Unable to assign (int) to a socket of type (std::string).
>>> b = []  # if you create a list object,
>>> a >> b  # you can use the right shift operator to append values to the list
['Hello!']

Todo

We should be able to extract values into a Python variable without needing it to be a list. In the example, b is a list, but this currently does not work with any other variable type.

compatible_type(other)

Some objects can be substituted and are considered compatible despite being different type.

Parameters:other (QuCellSocket) – The other socket for comparison.
Returns:Whether or not the compared objects are swappable.
Return type:Boolean
lshift()

Controls what happens when the overloaded << insertion operator is called on the socket.

Parameters:other (object) – The object to insert.

When a QuCellSocket is first initialized, it can take any type of value. Its type is determined as soon as the first object is inserted. The socket will try to store the object as a primitive data type if possible. For example, integers, strings, doubles, etc. If it is a more complex Python object, then the QuCellSocket will be able to hold any type of Python object. Type restriction is an optimization strategy. Complex types take longer to process and therefore Quantum prefers to use defined types whenever possible.

Tip

You can get around the type restriction by initializing the socket with a non-primitive type such as a list. In this case, the socket can accept any type of python object. Be aware that you may be introducing unneccessary computational overhead when you do this so use it sparingly. Example:

>>> a = QuCellSocket()
>>> a << 123  # now a can only hold ints
123
>>> a.type_name  # you can see its C++ data type
'int'
>>> b = QuCellSocket()
>>> b << []  # this is a complex object so b can now hold anything
[]
>>> b.type_name
'boost::python::api::object'
>>> b << 123  # this works
123
>>> b << 'abc'  # this works also!

A QuCellSocket can also validate values that you are trying to insert. Use the :func:set_validator to register validation functions. You may define the validation function to do anything you want, however, it must return a boolean.

reset()

Return the QuCellSocket to its initial state right after allocation. This allows the socket to accept a new data type.

reset_validator()

Removes all validation functions.

rshift()

Controls what happens when the overloaded >> right shift operator is called on a QuCellSocket.

Parameters:other (List) – The object receiving the contents of the QuCellSocket.

Currently, only lists are supported as the reciever of contents.

Todo

We should be able to support connecting sockets from script using the rshift function. Currently, it raises an error.

same_type(other)

Compares the current object type in the QuCellSocket to another QuCellSocket.

Parameters:other (QuCellSocket) – The other socket for comparison.
Returns:Whether or not the compared objects are the same type.
Return type:Boolean
set_validator(validation_func)

Register a python function that returns a boolean for validation of the socket value. You can register any number of functions. There is no guarantee on the order in which validation functions are called. For example, to add a validation function that checks if the value is an integer:

def is_integer(i):
    return isinstance(i, int)

my_socket.set_validator(is_integer)
Parameters:validation_func (Callable) – A python function that should recieve a single parameter and returns a boolean.
class Quantum.QuCellSockets

A dictionary structure containing QuCellSocket objects. Access the objects with the same syntax as a dict. This allows you to get a QuCellSocket from the CellSockets defined in C++.

Example:

Indexing into QuCellSockets
>>> inputs  # this is a QuCellSockets that we got from a QuCell.
<Quantum.QuCellSockets object at 0x118ba7ec8>
>>> inputs['msg']  # msg is the name of a CellSocket defined in C++
Hello!
>>> # You can see the socket holds the string value 'Hello!'
>>> inputs['msg'] << 'Goodbye!'  # we can insert values like this.

Warning

Currently, you cannot create new QuCellSockets from Python. Attempting to instance a QuCellSockets and accessing a non-existent key will crash the app. This will be fixed. We may provide the ability to instance new sockets and insert them into a QuCellSockets just like you would a Dict object, but currently I cannot think of a use-case where this would be useful so it is very low priority.

print_doc()

Provides formatted text describing the contents and properties of a particular socket.

Parameters:name (string) – The unique name of a QuCellSocket
Returns:Description of a particular QuCellSocket
Return type:string
class Quantum.QuCircuit

This binds to the underlying C++ Circuit object and exposes its functions to Python. In Quantum, a circuit models a directed acyclic graph. So a circuit contains cells and pipes which the scheduler can traverse to execute cell processes. A circuit manages cells and defines relationships between them.

activate_all()

Traverse all cells and call the activate() method on every cell.

configure_all()

Traverse all cells and call the configure() method on each.

connect(upstream, u, downstream, d)

Create a connection between two cells’ sockets.

Parameters:
  • upstream (QuCell) – The source cell.
  • u (String) – The key corresponding to the output socket you wish to connect.
  • downstream (QuCell) – The target cell.
  • d (String) – The key corresponding to the input socket you wish to connect.
disconnect(upstream, u, downstream, d)

Disconnect a connection that exists between two cells’ sockets.

Parameters:
  • upstream (QuCell) – The source cell.
  • u (String) – The key corresponding to the output socket you wish to disconnect.
  • downstream (QuCell) – The target cell.
  • d (String) – The key corresponding to the input socket you wish to disconnect.
insert(cell)

Inserts a new cell into the circuit

Parameters:cell (QuCell) – The new cell to insert.
remove(cell)

Removes a cell from the circuit.

Parameters:cell (QuCell) – The cell to remove.
reset_ticks()

Traverse all cells and reset their tick counts.

viz()

Produce a string in dot format that can be used to diagram the circuit.

class Quantum.QuEvent(val)

This converts the event enums from the C++ layer and makes them human readable in Python. This class can be pickled.

Parameters:

val (Integer or String) – An integer or string representing an event. Possible string values are: DEFAULT, PROCESSING, STOPPED, WRITING, CONNECT, DONE. It is not case-sensitive.

Variables:
  • int2str – A dict that can be used to convert between integer and string values.
  • str2int – A dict that can be used to convert between string and integer and string values.
  • status – The string representation of the event object.
  • value – The integer representation of the event object.
class Quantum.QuKernel

Manages an instance of the Quantum application. To start Quantum, a single QuKernel must be instantiated. Once a kernel has been instanced, all subsequent attempts to instance a kernel will return a reference to the existing copy. Assign the instance to a variable in order to control the application. For example

>>> from Quantum import QuKernel
>>> my_app = QuKernel()
Variables:root_directory – A string representing the root directory of Quantum. This is used to load plugins.
list_cells()
Returns:A list of unique cell name strings available to the system across all loaded plugins.
Return type:List
load_plugin(filename)

Specify a dynamic library file as a string parameter to load it as a plugin.

Parameters:filename (string) – The filename including extension but not path. The file must exist in the plugin directory under the root directory.
print_list()
Returns:A formatted string of cell names available to the system across all loaded plugins.
Return type:String
class Quantum.QuObservable

Derive from QuObservable to create an object that can be observed by the Observe object or any object deriving from QuObservable.

py_notify(event)

Send a signal to all registered observers that an observable event has occured. This will trigger the update() functions on all registered observers. This broadcasts the event to C++ observers.

Parameters:event (QuEvent) – An event object.
class Quantum.QuObserver(subject, observer)

Internal. For objects defined in C++ as Observer, they should be declared as deriving from QuObserver when exposed to Python.

Parameters:
  • subject (QuObservable) – The object to observe.
  • observer (Any Python object) – The observer object
class Quantum.QuReturnCode(val)

This converts C++ ReturnCodes, which is an enum type, into human-readable Python objects.

Parameters:

val (Integer or String) – The string or integer representation of a ReturnCode. The acceptable string values are: OK, QUIT, DO_OVER, BREAK, CONTINUE, UNKNOWN. These are case insensitive.

Variables:
  • int2str – A dict that converts integers to string values of ReturnCodes.
  • str2int – A dict that converts strings to integer values of ReturnCodes.
  • status – The string representation of a ReturnCode.
  • returncode – The integer representation of a ReturnCode.

ReturnCodes determine the execution path of graphs. For example, an if cell would have 2 outgoing execution sockets– one will hold the ReturnCode if the condition evaluates True and the other will hold the ReturnCode if the condition evaluates False. This allows Quantum’s scheduler to determine which execution path to follow.

The QuReturnCode object allows for seamless interoperability between C++ and Python. Some cells might be native C++ and others might be written in Python. QuReturnCode automatically converts itself to which ever type of cell it needs to communicate with. So you can connect the executuion of Python cells to C++ cells and vice-a-versa.

QuReturnCodes can be pickled.

class Quantum.QuScheduler(circuit)

The scheduler manages the order in which cell processing is executed within a circuit.

Parameters:

circuit (QuCircuit) – A reference to the managed circuit.

Variables:
  • debug – A switch to allow step by step cell calculation.
  • executing – Indicates if scheduler is executing.
  • running – Indicates is scheduler is running. A scheduler can be running but not executing. This happens when it is interrupted.
  • finished – Indicates if scheduler is finished running.
  • state – A human-readable state of the scheduler

Todo

Wrap Scheduler::State into a QuState

execute(iter=0)

Execute the underlying C++ scheduler.

Parameters:iter (Integer) – Number of iterations to execute.
stop()

Interrupt the scheduler and force it to stop executing.