Client gRPC services for running on FPGA reservoir computer EmuCore developed by QCi.

class emucore_direct.client.StatusMessage[source]

Bases: TypedDict

Structure of responses for configuration requests to EmuCore device.

  • status – the status of the request
  • message – a description for the recieved status
status: int
message: str
exception emucore_direct.client.InactiveRpcError[source]

Bases: Exception

Custom exception wrapper around grpc._channel._InactiveRpcError.

class emucore_direct.client.EmuCoreClient(ip_addr: str = 'localhost', port: str = '50051', max_data_size: int = 536870912)[source]

Bases: object

Provides services for accessing EmuCore server

  • ip_addr – the IP address of the gRPC server
  • port – The port that the RPC server is running on
  • max_data_size – int The max send and recieve message length for RPC server
check_lock(lock_id: str = '') dict[source]

Checks if submitted lock_id has execution lock on the device

lock_id – a UUID which will be checked to determine if has exclusive device execution lock

a member of eqc_direct.utils.LockCheckStatus as a dict:

  • status_code: int- status code for lock check
  • status_desc: str- a description for the associated status code
reservoir_reset(lock_id) StatusMessage[source]

Resets a reservoir instance by clearing RAM on the server

lock_id – a lock_id which has an active reserve on the device
dictionary with with values from members of emucore_direct.types.StatusResponses
system_info() dict[source]

Provides system info on call


dict with following keys:

  • system_name: str- product name
  • system_version: str- server version
acquire_lock() dict[source]

Attempts to acquire exclusive lock for submitting jobs


a member of emucore_direct.types.LockManageStatus as a dict along with an additional key lock_id:

  • lock_id: str- if acquired the current device lock_id else empty string
  • status: int- status code for lock id acquisition
  • message: str- a description for the associated status code

Releases exclusive lock for submitting data to reservoir

lock_id – a UUID with currently acquired exclusive device lock

a dict with the following keys:

  • lock_released: bool- if released is True else False
  • message: str- a description of release operation result
rc_config(lock_id: str, vbias: float, gain: float, num_nodes: int, num_taps: int) StatusMessage[source]

Configures reservoir model and how data will be processed by the reservoir.

  • lock_id – a lock_id which has an active reserve on the device
  • vbias – bias to apply to each node in reservoir. Range for parameter [0,1].
  • gain – memory setting for system how long should inputs effect reservoir similar to beta in adaptive gradient descent range for parameter [0,1]
  • num_nodes – the total number of hidden nodes to instantiate within the reservoir, a single hidden layer
  • num_taps – number of connections in reservoir, generally should be set to less than the number of nodes in reservoir. Defines interconnection between nodes.
dictionary with with values from one of the members of emucore_direct.types.StatusResponses
rc_run(lock_id: str, reservoir_input: List[int])[source]

Runs a series of data through the reservoir and returns response from device based on current reservoir configuration.

  • lock_id – a lock_id which has an active reserve on the device
  • reservoir_input – a list of digitized values to input to the reservoir must be less than MAX_INPUT_SIZE

a dictionary with the folowing keys:

  • status: int- the status for the reservoir submission
  • message: str- a description of the status for the submission
  • states: bytes- response from reservoir as bytes.

Waits for lock indefinitely calling acquire_lock()


a tuple of the following items:

  • lock_id: str- exclusive lock for device execution with a timeout
  • start_queue_ts: int- time in ns when began lock acquisition.
  • end_queue_ts: int- time in ns when lock was acquired.
process_all_data(lock_id: str, input_data: ndarray, num_nodes: int, density: float, feature_scaling: float, max_scale_val: float | None = None, weights: ndarray | None = None, seed_val_weights: int = 13)[source]

Run dataset through reservoir:

  1. Get lock
  2. Apply scaling and random weights mask to input data
  3. Run data through reservoir
  4. Combine data from reservoir responses and reshape based on number of nodes
  5. Release lock
  • lock_id – a UUID that currently has lock on the device
  • input_data – data or series to process via reservoir
  • num_nodes – the total number of hidden nodes to instantiate within the reservoir, a single hidden layer (this is also used to apply random weights to to the data as well as reshape data recieved from reservoir back to correct output dimension)
  • feature_scaling – after applying max abs scalar feature scaling factor applied
  • max_scale_val – max absolute value used to scale data if provided
  • seed_val_weights – seeds randomness for weigths to allow for reproducibility
if doing multiple runs without reset the max value mustn’t exceed original data max value in order for results to be processed properly.

a tuple of the following elements:

  • reservoir_response: np.ndarray- reservoir response represented as an array dimension of array will be nrows of input matrix by num nodes.
  • max_scale_value: np.ndarray- the scaling value that was applied to the input data before it was processed by the reservoir.
  • weights: np.ndarray- the weights that were used to apply the random mask to the data prior to being processed by the reservoir.


Documents possible responses from gRPC server for bumblebee client

class emucore_direct.types.StatusResponses[source]

Bases: object

status codes paired with their descriptions

NORMAL = {'message': 'Success', 'status': 0}
MISMATCH = {'message': "lock_id doesn't match current device lock", 'status': 1}
DEVICE_BUSY = {'message': 'Device currently processing other request', 'status': 2}
class emucore_direct.types.LockManageStatus[source]

Bases: object

Statuses and descriptions for acquiring and releasing lock

SUCCESS = {'message': 'Success', 'status': 0}
MISMATCH = {'message': 'lock_id does not match current device lock_id', 'status': 1}
BUSY = {'message': 'Lock currently in use unable to perform operation', 'status': 2}