eqc_direct.client
EqcClient
contains all gRPC calls to solve problems and monitor system
- exception eqc_direct.client.InactiveRpcError[source]
Bases:
Exception
Custom exception wrapper around grpc._channel._InactiveRpcError.
- class eqc_direct.client.SumConstrainedResult[source]
Bases:
TypedDict
Sum-constrained results object. Will not contain energy or solution if err_code is not 0. Contains nonempty distilled entries when solution_precision is not 0 or None.
- Parameters:
- err_code – the error code for a given job. Full list of
err_code
values can be foundeqc_direct.utils.JobCodes
- err_desc – the error description for a given job submission. Full list of
err_desc
values can be found ineqc_direct.utils.JobCodes
- preprocessing_time – data validation and time to re-format input data for running on the device in seconds
- runtime – sampling time in seconds for each solve on Dirac hardware
- energy – list of energies for best solution found (float32 precision) for each sample from Dirac hardware
- solution – a list of vectors representing the lowest energy solution (float32 precision) for each sample from Dirac hardware
- postprocessing_time – runtime for auxilary computations that occur besides sampling during each sample routine from Dirac hardware including intermediate energy calculations, objective function adjustments, and distillation of solutions
- distilled_energy – list of energies for distilled solution for input polynomial (float32 precision) for each sample from Dirac hardware
- distilled_solution – a vector representing the solution after the distillation procedure is applied to the original solution derived from the hardware. (float32 precision)
- calibration_time – calibration time is unrelated to execution of the individual sampling for the optimization. This time is from system level interruptions from calibrations that happen at regular intervals to maintain system performance.
- err_code – the error code for a given job. Full list of
- err_code: int
- err_desc: str
- num_samples: int
- num_variables: int
- preprocessing_time: float
- runtime: List[float]
- postprocessing_time: List[float]
- energy: List[float]
- solution: List[List[float]]
- distilled_energy: List[float]
- distilled_solution: List[List[float]]
- calibration_time: float
- class eqc_direct.client.IntegerResult[source]
Bases:
TypedDict
Integer solver results object. Will not contain 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 foundeqc_direct.utils.JobCodes
- err_desc – the error description for a given job submission. Full list of
err_desc
values can be found ineqc_direct.utils.JobCodes
- preprocessing_time – data validation and time to re-format input data for running on the device in seconds
- runtime – sampling time in seconds for each solve on Dirac hardware
- postprocessing_time – runtime for auxilary computations that occur besides sampling during each sample routine from Dirac hardware including intermediate energy calculations and objective function adjustments
- energy – list of energies of best solution found for each sample from Dirac hardware
- solution – list of vectors representing the lowest energy solution found by the device for each sample from Dirac hardware
- calibration_time – calibration time is unrelated to execution of the individual sampling for the optimization but it will occassionally interrupt execution to run calibration to maintain the system in order to provide transparency for total where time was spent solving a specific problem this value is provided
- err_code – the error code for a given job. Full list of
- err_code: int
- err_desc: str
- num_samples: int
- num_variables: int
- preprocessing_time: List[float]
- runtime: List[float]
- postprocessing_time: List[float]
- energy: List[float]
- solution: List[List[float]]
- class eqc_direct.client.EqcClient(ip_address: str = '', port: str = '', cert_file: str | None = None)[source]
Bases:
object
Client interface to communicate with EQC device.
- Parameters:
- ip_address – The IP address of the EQC device
- port – The port over which the gRPC server is communicating on the EQC device
- property ip_address: str
- Return configured IP address.
- property port: str
- Return configured IP port.
- property ip_add_port: str
- Return configured IP address + port, concatenated with a colon.
- submit_integer_job(poly_coefficients: List[float] | ndarray[Any, dtype[float32]], poly_indices: List[List[int]] | ndarray[Any, dtype[uint32]], num_levels: int | List[int] | ndarray[Any, dtype[uint16]], num_variables: int | None = None, num_samples: int = 1, lock_id: str = '', relaxation_schedule: int = 1, mean_photon_number: float | None = None, quantum_fluctuation_coefficient: int | None = None) → dict[source]
Submits a polynomial to be minimized by Dirac, with solutions restricted to integers between 0 and , where is the value in
num_levels
for each variable.- Parameters:
- poly_coefficients – Coefficient values for the polynomial to be minimized. Inputs should be precision float32 or less, as higher precision will be truncated.
- poly_indices – Index sets corresponding to the variables for each coefficient in the polynomial.
num_levels –
Specifies the number of discrete values (levels) each variable can take. A value of 2 means a variable can be {0, 1}, and in general, if is specified for variable , then its domain is .
- num_variables – Optional, specifies the number of variables in the polynomial. Must be greater than or
equal to the maximum index appearing in
poly_indices
. - num_samples – The number of samples (independent solutions) to generate from the device.
- lock_id – A UUID to coordinate multi-user access to the device.
- relaxation_schedule – An integer from the set {1, 2, 3, 4} indicating the type of analog relaxation schedule. Higher values reduce the variability in analog spin values, increasing the probability of reaching lower-energy solutions.
- mean_photon_number – Optional, overrides the default photon number associated with the selected
relaxation_schedule
. This sets the average number of photons present in a given quantum state. - quantum_fluctuation_coefficient – Optional, overrides the default value from
relaxation_schedule
. Specifies the number of photons () in each feedback loop, which determines the shot noise. Accepts integer values in the range [0, 100]. Shot noise scales inversely with the square root of the photon number:
- Returns:
A dictionary from
eqc_direct.utils.JobCodes
with the following keys:- err_code (int): Error code for the job submission.
- err_desc (str): Description corresponding to the error code.
- fetch_integer_result(lock_id: str = '') → IntegerResult[source]
Fetches results for last integer solve on Dirac device.
- Parameters:
- lock_id – a valid
lock_id
that matches current devicelock_id
- Returns:
- an
IntegerResult
object
- solve_integer(poly_coefficients: List[float] | ndarray[Any, dtype[float32]], poly_indices: List[List[int]] | ndarray[Any, dtype[uint32]], num_levels: int | List[int] | ndarray[Any, dtype[uint16]], num_variables: int | None = None, num_samples: int = 1, lock_id: str = '', relaxation_schedule: int = 1, mean_photon_number: float | None = None, quantum_fluctuation_coefficient: int | None = None) → dict[source]
Utilizes Dirac to optimize a polynomial with integer solution values.
- Parameters:
- poly_coefficients – the coefficient values for polynomial to be minimized. Inputs should be precision float 32 or less, otherwise precision is lost during conversion to 32-bit.
- poly_indices – the indices for coefficient values for polynomial to be minimized.
num_levels –
an array indicating the number of integer values for each solution variable. A
num_levels
value of 2 for a variable indicates that the possible values for that variable can be {0,1}. Similarily if :math`L` is specified for a given variable then possible values for that variable will be {0,1, …, -1}.- num_variables – optional input to specify number of variables for
polynomial. Must be greater than or equal to maximum index value in
poly_indices
. - num_samples – the number of times to solve the problem on the device.
- lock_id – a UUID to control multi-user device access.
- 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 (i.e., lower) objective function energy for input problem. Accepts range of values in set {1, 2, 3, 4}.
- mean_photon_number – optional parameter that modfies device
configuration from the defaults for
relaxation_schedule
. Sets the average number of photons that are present in a given quantum state. - quantum_fluctuation_coefficient – Optional, overrides the default value from
relaxation_schedule
. Specifies the number of photons () in each feedback loop, which determines the shot noise. Accepts integer values in the range [0, 100]. Shot noise scales inversely with the square root of the photon number:
- Returns:
- dict of results and timings with all keys from
IntegerResult
as well as the following additional keys:
- start_job_ts: time in ns marking start of job_submission
- end_job_ts: time in ns marking end of job submission complete includes
- Note:
- The difference between end_job_ts and start_job_ts includes a 1 second polling time which is not part of device solving time. To calculate the execution time on the device add together preprocessing_time, runtime and postprocessing_time from results object samplewise.
- submit_sum_constrained_job(poly_coefficients: List[float] | ndarray[Any, dtype[float32]], poly_indices: List[List[int]] | ndarray[Any, dtype[uint32]], num_variables: int | None = None, num_samples: int = 1, lock_id: str = '', relaxation_schedule: int = 1, sum_constraint: int | float = 10000, solution_precision: float | None = None, mean_photon_number: float | None = None, quantum_fluctuation_coefficient: int | None = None) → dict[source]
Submits polynomial to be minimized by Dirac. All solutions are optimized utilizing a sum constraint which limits search to only solutions which have a sum equal to the input sum constraint.
- Parameters:
- poly_coefficients – the coefficient values for polynomial to be minimized. Numbers, including integers, should be floats with 32-bit (or less) precision, otherwise precision is lost during conversion to 32-bit.
- poly_indices – the indices for coefficient values for polynomial to be minimized.
- num_variables – optional input to specify number of variables for
polynomial. Must be greater than or equal to maximum index value in
poly_indices
. - num_samples – the number of times to solve the problem on the device.
- lock_id – a UUID to allow for multi-user processing
- 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}.
- 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. - 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
. Inputsolution_precision
must satisfysolution_precision
greater than or equal tosum_constraint
/10000 in order to be valid. Alsosum_constraint
must be divisible bysolution_precision
. Ifsolution_precision
is not specified no distillation will be applied to the solution derived by the device. - mean_photon_number – optional parameter that modfies device
configuration from the defaults for
relaxation_schedule
. Sets the average number of photons that are present in a given quantum state. - quantum_fluctuation_coefficient – Optional, overrides the default value from
relaxation_schedule
. Specifies the number of photons () in each feedback loop, which determines the shot noise. Accepts integer values in the range [0, 100]. Shot noise scales inversely with the square root of the photon number:
- 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_sum_constrained_result(lock_id: str = '') → SumConstrainedResult[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 devicelock_id
- Returns:
- an
EqcResult
object
- solve_sum_constrained(poly_coefficients: List[float] | ndarray[Any, dtype[float32]], poly_indices: List[List[int]] | ndarray[Any, dtype[uint32]], num_variables: int | None = None, num_samples: int = 1, lock_id: str = '', relaxation_schedule: int = 1, sum_constraint: int | float = 10000, solution_precision: float | None = None, mean_photon_number: float | None = None, quantum_fluctuation_coefficient: int | None = None) → dict[source]
Utilizes Dirac to optimize a polynomial under the constraint that the sum of the solution values must equal the input
sum_constraint
.- Parameters:
- poly_coefficients – the coefficient values for polynomial to be minimized. Numbers, including integers, should be floats with 32-bit (or less) precision, otherwise precision is lost during conversion to 32-bit.
- poly_indices – the indices for coefficient values for polynomial to be minimized.
- num_variables – optional input to specify number of variables for
polynomial. Must be greater than or equal to maximum index value in
poly_indices
. - num_samples – the number of times to solve the problem on the device.
- lock_id – a UUID to allow for multi-user processing
- 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}.
- 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. - 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
. Inputsolution_precision
must satisfysolution_precision
greater than or equal tosum_constraint
/10000 in order to be valid. Alsosum_constraint
must be divisible bysolution_precision
. Ifsolution_precision
is not specified no distillation will be applied to the solution derived by the device. - mean_photon_number – optional parameter that modfies device
configuration from the defaults for
relaxation_schedule
. Sets the average number of photons that are present in a given quantum state. - quantum_fluctuation_coefficient – Optional, overrides the default value from
relaxation_schedule
. Specifies the number of photons () in each feedback loop, which determines the shot noise. Accepts integer values in the range [0, 100]. Shot noise scales inversely with the square root of the photon number:
- Returns:
dict of results and timings with the following keys:
- results:
SumConstrainedResult
dict - start_job_ts: time in ns marking start of job_submission
- end_job_ts: time in ns marking end of job submission complete
- results:
- Note:
- The difference between end_job_ts and start_job_ts includes a 1 second polling time which is not part of device solving time. To calculate the execution time on the device add together preprocessing_time, runtime and postprocessing_time from results object samplewise.
- 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 keylock_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_info() → SystemInfo[source]
Provides information regarding Dirac system
- Returns:
a
eqc_direct.utils.SystemInfo
dict with a these items:- server_version: str - the gRPC server version
- device_type: str - the device type (e.g., Dirac-3)
- fpga_version: str - version of FPGA in device (None if using the simulator)
eqc_direct.utils
Utilities for running server sim and client
- class eqc_direct.utils.SystemInfoOptional[source]
Bases:
TypedDict
Python binding to SystemInfo->VersionOutput proto spec optional fields.
- device_id: str
- class eqc_direct.utils.SystemInfo[source]
Bases:
dict
Python binding to SystemInfo->VersionOutput proto spec.
- server_version: str
- device_type: str
- device_id: str
- 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], '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'}
- NUM_SAMPLES_POSITIVE = {'err_code': 12, 'err_desc': 'Input num_samples must be positive.'}
- 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'}
- NUM_LEVELS_NUM_VARS_MISMATCH = {'err_code': 17, 'err_desc': 'Length of `num_levels` input must be equal to num_variables'}
- NUM_LEVELS_GT_ONE = {'err_code': 18, 'err_desc': 'All elements of input `num_levels` must be greater than 1'}
- TOTAL_INTEGER_LEVELS = {'err_code': 19, 'err_desc': 'Total number of integer levels from input variables exceeds limit'}
- INVALID_MEAN_PHOTON_NUMBER = {'err_code': 20, 'err_desc': 'Mean photon number if specified must be in range [0.0000667, 0.0066666]'}
- INVALID_QUANTUM_FLUCTUATION_COEFFICIENT = {'err_code': 21, 'err_desc': 'Quantum fluctuation coefficient if specified must be in range [1, 100]'}
- 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]
Helper function which gets the number of decimal places for a float, excluding trailing zeros.
- Parameters:
- float_num – float input for which decimal places will be found
- Returns:
- a non-negative integer representing the number of decimal places