Source code for eqc_direct.utils
- """
- Utilities for running server sim and client
- """
- from dataclasses import dataclass
- from typing import List, Tuple, TypedDict
- import numpy as np
- PREC_MIN_RECOMMENDED_LEVELS = 200
- PREC_MAX_LEVELS = 10000
- [docs]
- class SystemInfo(TypedDict):
-     """Python binding to SystemInfo->VersionOutput proto spec."""
-     server_version: str
-     fpga_version: str
-     device_type: str
-     device_id: str
- [docs]
- @dataclass
- class SysStatus:
-     """
-     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"}
- [docs]
- @dataclass
- class LockCheckStatus:
-     """
-     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",
-     }
- [docs]
- @dataclass
- class LockManageStatus:
-     """
-     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",
-     }
- [docs]
- @dataclass
- class JobCodes:
-     """
-     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]",
-     }
- [docs]
- def message_to_dict(grpc_message) -> dict:
-     """Convert a gRPC message to a dictionary."""
-     result = {}
-     for descriptor in grpc_message.DESCRIPTOR.fields:
-         field = getattr(grpc_message, descriptor.name)
-         if descriptor.type == descriptor.TYPE_MESSAGE:
-             
-             if descriptor.label == descriptor.LABEL_REPEATED:
-                 if descriptor.message_type and any(
-                     subfield.label == subfield.LABEL_REPEATED
-                     for subfield in descriptor.message_type.fields
-                 ):
-                     
-                     result[descriptor.name] = (
-                         [list(item.values) for item in field] if field else []
-                     )
-                 else:
-                     
-                     result[descriptor.name] = (
-                         [message_to_dict(item) for item in field] if field else []
-                     )
-             else:
-                 
-                 result[descriptor.name] = message_to_dict(field) if field else {}
-         else:
-             
-             if descriptor.label == descriptor.LABEL_REPEATED:
-                 result[descriptor.name] = list(field) if field else []
-             else:
-                 result[descriptor.name] = field
-     return result
- [docs]
- def get_decimal_places(float_num: float) -> int:
-     """
-     Helper function which gets the number of decimal places for a float,
-     excluding trailing zeros.
-     :param float_num: float input for which decimal places will be found
-     :return: a non-negative integer representing the number of decimal places
-     """
-     try:
-         
-         _, fractional_part = str(float_num).split(".")
-         
-         fractional_part = fractional_part.rstrip("0")
-         decimal_places = len(fractional_part)
-     except ValueError:
-         
-         decimal_places = 0
-     return decimal_places