eqc_direct

eqc_direct.client

EqcClient contains all RPC calls to process, get system status, and fetch results.

exception eqc_direct.client.InactiveRpcError[source]

Bases: Exception

Custom exception wrapper around grpc._channel._InactiveRpcError.

class eqc_direct.client.EqcResult[source]

Bases: TypedDict

EQC results object. Will not contain a energy or solution if err_code is not 0.

Parameters:
  • err_code – the error code for a given job. Full list of err_code values can be found eqc_direct.utils.JobCodes
  • err_desc – the error description for a given job submission. Full list of err_desc values can be found in eqc_direct.utils.JobCodes
  • preprocessing_time – data validation and time to re-format input data for running on the device in seconds
  • runtime – solving time in seconds for Dirac hardware
  • energy – energy for best solution found (float32 precision)
  • solution – vector representing the lowest energy solution (float32 precision)
  • distilled_runtime – runtime for distillation of solutions in seconds
  • distilled_energy – energy for distilled solution for input polynomial (float32 precision)
  • distilled_solution – a vector representing the solution after the distillation procedure is applied to the original solution derived from the hardware. (float32 precision)
Note:
  • solutions are length n vector of floats that sum to the device constraint
err_code: int
err_desc: str
preprocessing_time: float
runtime: float
energy: float | None
solution: List[float] | None
distilled_runtime: float | None
distilled_energy: float | None
distilled_solution: List[float] | None
class eqc_direct.client.EqcClient(ip_address: str = 'localhost', port: str = '50051', max_data_size: int = 536870912)[source]

Bases: object

Provides calls to process jobs using EQC RPC server

Parameters:
  • ip_address – The IP address of the RPC server
  • port – The port that the RPC server is running on
  • max_data_size – the max send and recieve message length for RPC server
submit_job(poly_coefficients: ndarray, poly_indices: ndarray, num_variables: int | None = None, lock_id: str = '', sum_constraint: int | float = 10000, relaxation_schedule: int = 2, solution_precision: float | None = None) dict[source]

Submits data to be processed by EQC device

Parameters:
  • poly_coefficients – coefficient values for the polynomial to be minimized
  • poly_indices – list of lists containing polynomial indices associated with coefficient values for problem to be optimized.
  • num_variables – the number of total variables for the submitted polynomial must not be less than max index in poly_indices. If no value is provided then will be set to max value in poly_indices.
  • lock_id – a UUID to allow for multi-user processing
  • sum_constraint – a normalization constraint that is applied to the problem space that is used to calculate energy. This parameter will be rounded if exceeds float32 precision (e.g. 7-decimal places). Value must be between 1 and 10000.
  • relaxation_schedule – four different schedules represented in integer parameter. Higher values reduce the variation in the analog spin values and therefore, are more probable to lead to improved objective function energy for input problem. Accepts range of values in set {1, 2, 3, 4}.
  • solution_precision – the level of precision to apply to the solutions. This parameter will be rounded if exceeds float32 precision (e.g. 7-decimal places). If specified a distillation method is applied to the continuous solutions to map them to the submitted solution_precision. Input solution_precision must satisfy solution_precision greater than or equal to sum_constraint/10000 in order to be valid. Also sum_constraint must be divisible by solution_precision. If solution_precision is not specified no distillation will be applied to the solution derived by the device.
Returns:

a member of eqc_direct.utils.JobCodes as a dict with the following keys:

  • err_code: int- job submission error code
  • err_desc: str- error code description for submission
fetch_result(lock_id: str = '') EqcResult[source]

Request last EQC job results. Returns results from the most recent run on the device.

Parameters:
lock_id – a valid lock_id that matches current device lock_id
Returns:
an EqcResult object
system_status() dict[source]

Client call to obtain EQC system status

Returns:

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

  • status_code: int- current system status code
  • status_desc: str- description of current system status
acquire_lock() dict[source]

Makes a single attempt to acquire exclusive lock on hardware execution. Locking can be used to ensure orderly processing in multi-user environments. Lock can only be acquired when no other user has acquired the lock or when the system has been idle for 60 seconds while another user has the lock. This idle timeout prevents one user from blocking other users from using the machine even if they are not active.

Returns:

a member of eqc_direct.utils.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_code: int- status code for lock id acquisition
  • status_desc: str- a description for the associated status code
release_lock(lock_id: str = '') dict[source]

Releases exclusive lock for running health check or submitting job

Parameters:
lock_id – a UUID with currently acquired exclusive device lock
Returns:

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

  • status_code: int- status code for lock id acquisition
  • status_desc: str- a description for the associated status code
check_lock(lock_id: str = '') dict[source]

Checks if submitted lock_id has execution lock on the device

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

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
stop_running_process(lock_id: str = '') dict[source]

Stops a running process either a health check or a Eqc job. Process locks will release automatically based on a timeout which is maintained in the server code if they are not released using this.

Parameters:
lock_id – requires a lock_id that was acquired by
Returns:

a member of eqc_direct.utils.SysStatus as dict with following keys:

  • status_code: int- the system code after stopping
  • status_desc: str- the associated system status description
wait_for_lock() tuple[source]

Waits for lock indefinitely calling acquire_lock()

Returns:

a tuple of the following items:

  • lock_id: str- exclusive lock for device execution with a timeout
  • start_queue_ts: int- time in ns on which lock was acquired is an int
  • end_queue_ts: int- time in ns on which queue for lock ended is an int.
system_version() dict[source]

Provides information regarding Dirac server

Returns:

a dict with a single item:

  • server_version: str - the current gRPC server version
process_job(poly_coefficients: ndarray, poly_indices: ndarray, num_variables: int | None = None, lock_id: str = '', sum_constraint: int | float = 10000, relaxation_schedule: int = 2, solution_precision: float | None = None) dict[source]
Processes a job by:
  1. Submitting job
  2. Checks for status, until completes or fails
  3. Returns results
Parameters:
  • poly_coefficients – coefficient values for the polynomial to be minimized
  • poly_indices – list of lists containing polynomial indices associated with coefficient values for problem to be optimized.
  • lock_id – a UUID to allow for multi-user processing
  • sum_constraint – a normalization constraint that is applied to the problem space that is used to calculate energy. This parameter will be rounded if exceeds float32 precision (e.g. 7-decimal places). Value must be between 1 and 10000.
  • relaxation_schedule – four different schedules represented in integer parameter. Higher values reduce the variation in the analog spin values and therefore, are more probable to lead to improved objective function energy for input problem. Accepts range of values in set {1, 2, 3, 4}.
  • solution_precision – the level of precision to apply to the solutions. This parameter will be rounded if exceeds float32 precision (e.g. 7-decimal places). If specified a distillation method is applied to the continuous solutions to map them to the submitted solution_precision. Input solution_precision must satisfy solution_precision greater than or equal to sum_constraint/10000 in order to be valid. Also sum_constraint must be divisible by solution_precision. If solution_precision is not specified no distillation will be applied to the solution derived by the device.
Returns:

dict of results and timings with the following keys:

  • results: EqcResult dict
  • start_job_ts: time in ns marking start of job_submission
  • end_job_ts: time in ns marking end of job submission complete

eqc_direct.utils

Utilities for running server sim and client

class eqc_direct.utils.SysStatus[source]

Bases: object

Status codes for system paired with their descriptions.

IDLE = {'status_code': 0, 'status_desc': 'IDLE'}
JOB_RUNNING = {'status_code': 1, 'status_desc': 'JOB_RUNNING'}
CALIBRATION = {'status_code': 2, 'status_desc': 'CALIBRATION'}
HEALTH_CHECK = {'status_code': 3, 'status_desc': 'HEALTH_CHECK'}
HARDWARE_FAILURE = {'status_code': [4, 5, 6, 7], 'status_desc': 'HARDWARE_FAILURE'}
class eqc_direct.utils.LockCheckStatus[source]

Bases: object

Statuses codes for checking lock status paired with their descriptions

AVAILABLE = {'status_code': 0, 'status_desc': 'Lock available'}
USER_LOCKED = {'status_code': 1, 'status_desc': 'lock_id matches current server lock_id'}
UNAVAILABLE = {'status_code': 2, 'status_desc': 'Execution lock is in use by another user'}
class eqc_direct.utils.LockManageStatus[source]

Bases: object

Statuses and descriptions for acquiring and releasing lock

SUCCESS = {'status_code': 0, 'status_desc': 'Success'}
MISMATCH = {'status_code': 1, 'status_desc': 'lock_id does not match current device lock_id'}
BUSY = {'status_code': 2, 'status_desc': 'Lock currently in use unable to perform operation'}
class eqc_direct.utils.JobCodes[source]

Bases: object

Job codes for errors paired with their descriptions

NORMAL = {'err_code': 0, 'err_desc': 'Success'}
INDEX_OUT_OF_RANGE = {'err_code': 1, 'err_desc': 'Index in submitted data is out of range for specified number of variables'}
COEF_INDEX_MISMATCH = {'err_code': 2, 'err_desc': 'Polynomial indices do not match required length for specified coefficient length'}
DEVICE_BUSY = {'err_code': 3, 'err_desc': 'Device currently processing other request'}
LOCK_MISMATCH = {'err_code': 4, 'err_desc': "lock_id doesn't match current device lock"}
HARDWARE_FAILURE = {'err_code': 5, 'err_desc': 'Device failed during execution'}
INVALID_SUM_CONSTRAINT = {'err_code': 6, 'err_desc': 'Sum constraint must be greater than or equal to 1 and less than or equal to 10000'}
INVALID_RELAXATION_SCHEDULE = {'err_code': 7, 'err_desc': 'Parameter relaxation_schedule must be in set {1,2,3,4}'}
USER_INTERRUPT = {'err_code': 8, 'err_desc': 'User sent stop signal before result was returned'}
EXCEEDS_MAX_SIZE = {'err_code': 9, 'err_desc': 'Exceeds max problem size for device'}
DECREASING_INDEX = {'err_code': 10, 'err_desc': 'One of specified polynomial indices is not specified in non-decreasing order'}
INVALID_PRECISION = {'err_code': 11, 'err_desc': 'The input precision exceeds maximum allowed precision for device'}
DUPLICATE_INDEX = {'err_code': 12, 'err_desc': 'A duplicate polynomial index set was specified for the input polynomial'}
PRECISION_CONSTRAINT_MISMATCH = {'err_code': 13, 'err_desc': 'Sum constraint must be divisible by solution_precision'}
PRECISION_NONNEGATIVE = {'err_code': 14, 'err_desc': 'Input solution precision cannot be negative'}
DEGREE_POSITIVE = {'err_code': 15, 'err_desc': 'Input degree must be greater than 0'}
NUM_VARIABLES_POSITIVE = {'err_code': 16, 'err_desc': 'Input num_variables must be greater than 0'}
eqc_direct.utils.message_to_dict(grpc_message) dict[source]
Convert a gRPC message to a dictionary.
eqc_direct.utils.convert_hamiltonian_to_poly_format(linear_terms: ndarray, quadratic_terms: ndarray) Tuple[List[List[int]], List[float]][source]

Converts linear terms and quadratic terms of Hamiltonian to polynomial index formatting for Dirac device

Parameters:
  • linear_terms – the linear terms for the Hamiltonian 1D length n array
  • quadratic_terms – the quadratic coefficients of the Hamiltonian (n by n)
Returns:

a tuple with the following members:

  • poly_indices: List[List[int]] - polynomial indices in non-decreasing sparse format
  • poly_coefficients: List[float] - polynomial coefficients in sparse format
eqc_direct.utils.get_decimal_places(float_num: float) int[source]