classiq 0.36.0__py3-none-any.whl → 0.37.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. classiq/__init__.py +1 -0
  2. classiq/_internals/api_wrapper.py +24 -6
  3. classiq/_internals/authentication/device.py +6 -3
  4. classiq/_internals/authentication/token_manager.py +21 -5
  5. classiq/_internals/client.py +7 -2
  6. classiq/_internals/config.py +12 -0
  7. classiq/_internals/host_checker.py +1 -1
  8. classiq/_internals/jobs.py +3 -1
  9. classiq/_internals/type_validation.py +3 -6
  10. classiq/analyzer/analyzer.py +1 -0
  11. classiq/analyzer/rb.py +3 -5
  12. classiq/applications_model_constructors/chemistry_model_constructor.py +42 -67
  13. classiq/applications_model_constructors/grover_model_constructor.py +27 -18
  14. classiq/exceptions.py +5 -0
  15. classiq/execution/jobs.py +13 -4
  16. classiq/executor.py +3 -2
  17. classiq/interface/_version.py +1 -1
  18. classiq/interface/analyzer/analysis_params.py +0 -6
  19. classiq/interface/analyzer/result.py +0 -4
  20. classiq/interface/backend/backend_preferences.py +2 -2
  21. classiq/interface/backend/quantum_backend_providers.py +1 -1
  22. classiq/interface/execution/resource_estimator.py +7 -0
  23. classiq/interface/execution/result.py +5 -0
  24. classiq/interface/executor/register_initialization.py +3 -1
  25. classiq/interface/executor/vqe_result.py +1 -0
  26. classiq/interface/generator/ansatz_library.py +3 -3
  27. classiq/interface/generator/arith/argument_utils.py +4 -4
  28. classiq/interface/generator/arith/arithmetic.py +4 -2
  29. classiq/interface/generator/arith/arithmetic_arg_type_validator.py +11 -5
  30. classiq/interface/generator/arith/arithmetic_expression_parser.py +8 -7
  31. classiq/interface/generator/arith/arithmetic_operations.py +7 -0
  32. classiq/interface/generator/arith/arithmetic_param_getters.py +97 -16
  33. classiq/interface/generator/arith/arithmetic_result_builder.py +13 -3
  34. classiq/interface/generator/arith/binary_ops.py +8 -10
  35. classiq/interface/generator/arith/extremum_operations.py +2 -2
  36. classiq/interface/generator/arith/number_utils.py +20 -23
  37. classiq/interface/generator/arith/register_user_input.py +3 -1
  38. classiq/interface/generator/arith/unary_ops.py +9 -13
  39. classiq/interface/generator/expressions/atomic_expression_functions.py +2 -0
  40. classiq/interface/generator/expressions/expression.py +7 -2
  41. classiq/interface/generator/expressions/qmod_qnum_proxy.py +22 -0
  42. classiq/interface/generator/expressions/qmod_sized_proxy.py +2 -12
  43. classiq/interface/generator/functions/core_lib_declarations/quantum_functions/atomic_quantum_functions.py +63 -3
  44. classiq/interface/generator/functions/core_lib_declarations/quantum_functions/std_lib_functions.py +143 -17
  45. classiq/interface/generator/functions/core_lib_declarations/quantum_operators.py +41 -16
  46. classiq/interface/generator/functions/native_function_definition.py +3 -3
  47. classiq/interface/generator/model/constraints.py +3 -3
  48. classiq/interface/generator/model/preferences/preferences.py +13 -9
  49. classiq/interface/generator/noise_properties.py +5 -5
  50. classiq/interface/generator/qpe.py +5 -5
  51. classiq/interface/generator/quantum_function_call.py +5 -3
  52. classiq/interface/generator/randomized_benchmarking.py +5 -3
  53. classiq/interface/generator/visitor.py +1 -2
  54. classiq/interface/hardware.py +1 -1
  55. classiq/interface/helpers/custom_pydantic_types.py +6 -0
  56. classiq/interface/model/{modular_addition_operation.py → inplace_binary_operation.py} +16 -2
  57. classiq/interface/model/native_function_definition.py +2 -24
  58. classiq/interface/model/operator_synthesis_data.py +6 -0
  59. classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +8 -4
  60. classiq/interface/model/quantum_expressions/arithmetic_operation.py +9 -5
  61. classiq/interface/model/quantum_expressions/control_state.py +38 -0
  62. classiq/interface/model/quantum_expressions/quantum_expression.py +21 -11
  63. classiq/interface/model/quantum_function_call.py +81 -6
  64. classiq/interface/model/quantum_function_declaration.py +3 -3
  65. classiq/interface/model/quantum_if_operation.py +95 -0
  66. classiq/interface/model/resolvers/function_call_resolver.py +1 -1
  67. classiq/interface/model/validations/handles_validator.py +42 -15
  68. classiq/interface/server/routes.py +10 -6
  69. classiq/model/function_handler.pyi +86 -86
  70. classiq/model/model.py +1 -0
  71. classiq/qmod/__init__.py +6 -1
  72. classiq/qmod/builtins/__init__.py +13 -1
  73. classiq/qmod/builtins/classical_execution_primitives.py +109 -0
  74. classiq/qmod/builtins/classical_functions.py +68 -0
  75. classiq/qmod/builtins/functions.py +88 -18
  76. classiq/qmod/builtins/operations.py +60 -35
  77. classiq/qmod/classical_function.py +40 -0
  78. classiq/qmod/declaration_inferrer.py +5 -2
  79. classiq/qmod/qmod_variable.py +17 -10
  80. classiq/qmod/quantum_callable.py +24 -3
  81. classiq/qmod/quantum_expandable.py +131 -21
  82. classiq/qmod/quantum_function.py +12 -2
  83. classiq/qmod/symbolic.py +182 -107
  84. classiq/qmod/symbolic_expr.py +11 -10
  85. classiq/qmod/symbolic_type.py +8 -0
  86. classiq/quantum_functions/decorators.py +2 -4
  87. classiq/quantum_functions/function_library.py +1 -0
  88. {classiq-0.36.0.dist-info → classiq-0.37.0.dist-info}/METADATA +1 -1
  89. {classiq-0.36.0.dist-info → classiq-0.37.0.dist-info}/RECORD +90 -82
  90. classiq/interface/model/local_variable_declaration.py +0 -7
  91. {classiq-0.36.0.dist-info → classiq-0.37.0.dist-info}/WHEEL +0 -0
classiq/execution/jobs.py CHANGED
@@ -7,9 +7,9 @@ from classiq.interface.execution.jobs import ExecutionJobDetailsV1
7
7
  from classiq.interface.executor.execution_request import ExecutionJobDetails
8
8
  from classiq.interface.executor.execution_result import ResultsCollection
9
9
  from classiq.interface.jobs import JobStatus, JSONObject
10
- from classiq.interface.server.routes import EXECUTION_JOBS_FULL_PATH
10
+ from classiq.interface.server.routes import EXECUTION_JOBS_NON_VERSIONED_FULL_PATH
11
11
 
12
- from classiq._internals.api_wrapper import ApiWrapper
12
+ from classiq._internals.api_wrapper import CLASSIQ_ACCEPT_HEADER, ApiWrapper
13
13
  from classiq._internals.async_utils import syncify_function
14
14
  from classiq._internals.client import client
15
15
  from classiq._internals.jobs import JobID, JobPoller
@@ -17,6 +17,9 @@ from classiq.exceptions import ClassiqAPIError
17
17
 
18
18
  _JobDetails = Union[ExecutionJobDetails, ExecutionJobDetailsV1]
19
19
 
20
+ _JOB_DETAILS_VERSION = "v1"
21
+ _JOB_RESULT_VERSION = "v1"
22
+
20
23
 
21
24
  class ExecutionJob:
22
25
  _details: _JobDetails
@@ -98,7 +101,9 @@ class ExecutionJob:
98
101
 
99
102
  if self._result is None:
100
103
  self._result = (
101
- await ApiWrapper.call_get_execution_job_result(self._job_id)
104
+ await ApiWrapper.call_get_execution_job_result(
105
+ job_id=self._job_id, version=_JOB_RESULT_VERSION
106
+ )
102
107
  ).results
103
108
  return self._result
104
109
 
@@ -117,7 +122,11 @@ class ExecutionJob:
117
122
  return True
118
123
  return None
119
124
 
120
- poller = JobPoller(base_url=EXECUTION_JOBS_FULL_PATH)
125
+ poller = JobPoller(
126
+ base_url=EXECUTION_JOBS_NON_VERSIONED_FULL_PATH,
127
+ use_versioned_url=False,
128
+ additional_headers={CLASSIQ_ACCEPT_HEADER: _JOB_DETAILS_VERSION},
129
+ )
121
130
  await poller.poll(
122
131
  job_id=self._job_id,
123
132
  response_parser=response_parser,
classiq/executor.py CHANGED
@@ -1,4 +1,5 @@
1
1
  """Executor module, implementing facilities for executing quantum programs using Classiq platform."""
2
+
2
3
  import functools
3
4
  from typing import Optional, Tuple, Union
4
5
 
@@ -32,8 +33,8 @@ from classiq.synthesis import SerializedQuantumProgram
32
33
 
33
34
  BatchExecutionResult: TypeAlias = Union[ExecutionDetails, BaseException]
34
35
  ProgramAndResult: TypeAlias = Tuple[QuantumProgram, BatchExecutionResult]
35
- BackendPreferencesProgramAndResult: TypeAlias = Tuple[
36
- BackendPreferencesTypes, QuantumProgram, BatchExecutionResult
36
+ BackendPreferencesAndResult: TypeAlias = Tuple[
37
+ BackendPreferencesTypes, int, BatchExecutionResult
37
38
  ]
38
39
  _MAX_ARGUMENTS_SIZE = 1024
39
40
 
@@ -3,5 +3,5 @@ from packaging.version import Version
3
3
  # This file was generated automatically
4
4
  # Please don't track in version control (DONTTRACK)
5
5
 
6
- SEMVER_VERSION = '0.36.0'
6
+ SEMVER_VERSION = '0.37.0'
7
7
  VERSION = str(Version(SEMVER_VERSION))
@@ -51,12 +51,6 @@ class AnalysisHardwareListParams(AnalysisParams, HardwareListParams):
51
51
  transpilation_params: AnalysisHardwareTranspilationParams
52
52
 
53
53
 
54
- class ResourceEstimatorParams(pydantic.BaseModel):
55
- circuit_id: str
56
- error_budget: float
57
- physical_error_rate: float
58
-
59
-
60
54
  class HardwareParams(pydantic.BaseModel):
61
55
  device: PydanticNonEmptyString = pydantic.Field(default=None, description="Devices")
62
56
  provider: AnalyzerProviderVendor
@@ -136,10 +136,6 @@ class DevicesResult(VersionedModel):
136
136
  status: GraphStatus
137
137
 
138
138
 
139
- class ResourceEstimatorResult(VersionedModel):
140
- report_json: str
141
-
142
-
143
139
  class QuantumCircuitProperties(pydantic.BaseModel):
144
140
  depth: pydantic.NonNegativeInt = pydantic.Field(
145
141
  default=..., description="Circuit depth"
@@ -204,8 +204,8 @@ class GCPBackendPreferences(BackendPreferences):
204
204
 
205
205
  class OQCBackendPreferences(BackendPreferences):
206
206
  backend_service_provider: ProviderTypeVendor.OQC
207
- oqc_email: str = pydantic.Field(description="OQC Email")
208
- oqc_password: str = pydantic.Field(description="OQC email password")
207
+ username: str = pydantic.Field(description="OQC username")
208
+ password: str = pydantic.Field(description="OQC password")
209
209
 
210
210
  @pydantic.root_validator(pre=True)
211
211
  def _set_backend_service_provider(cls, values: Dict[str, Any]) -> Dict[str, Any]:
@@ -16,7 +16,7 @@ class ProviderVendor(StrEnum):
16
16
  AMAZON_BRAKET = "Amazon Braket"
17
17
  IONQ = "IonQ"
18
18
  GOOGLE = "Google"
19
- ALICE_AND_BOB = "Alice and Bob"
19
+ ALICE_AND_BOB = "Alice & Bob"
20
20
  OQC = "OQC"
21
21
 
22
22
 
@@ -0,0 +1,7 @@
1
+ import pydantic
2
+
3
+
4
+ class ResourceEstimatorParams(pydantic.BaseModel):
5
+ circuit_id: str
6
+ error_budget: float
7
+ physical_error_rate: float
@@ -0,0 +1,5 @@
1
+ from classiq.interface.helpers.versioned_model import VersionedModel
2
+
3
+
4
+ class ResourceEstimatorResult(VersionedModel):
5
+ report_json: str
@@ -30,7 +30,9 @@ class RegisterInitialization(pydantic.BaseModel):
30
30
  initial_condition: int = values.get("initial_condition", 0)
31
31
  name: str = values.get("name", "")
32
32
 
33
- initial_condition_length = number_utils.size(initial_condition)
33
+ initial_condition_length = number_utils.size(
34
+ initial_condition, machine_precision=number_utils.MAX_FRACTION_PLACES
35
+ )
34
36
  register_length = len(qubits)
35
37
  if initial_condition_length > register_length:
36
38
  raise ClassiqStateInitializationError(
@@ -51,6 +51,7 @@ class VQEIntermediateData(BaseModel):
51
51
 
52
52
  class VQESolverResult(SolverResult, QmodPyObject):
53
53
  eigenstate: Dict[str, Complex]
54
+ reduced_probabilities: Optional[Dict[str, float]] = None
54
55
  optimized_circuit_sample_results: ExecutionDetails
55
56
  intermediate_results: List[VQEIntermediateData]
56
57
  optimal_parameters: Dict[str, float]
@@ -52,9 +52,9 @@ class RandomTwoQubitGatesArgs(CustomAnsatzArgs):
52
52
 
53
53
 
54
54
  class TwoLocalArgs(CustomAnsatzArgs):
55
- rotation_blocks: Optional[
56
- Union[RotationBlocksType, List[RotationBlocksType]]
57
- ] = RotationBlocksType.ry
55
+ rotation_blocks: Optional[Union[RotationBlocksType, List[RotationBlocksType]]] = (
56
+ RotationBlocksType.ry
57
+ )
58
58
  entanglement_blocks: Optional[
59
59
  Union[EntanglementBlocksType, List[EntanglementBlocksType]]
60
60
  ] = EntanglementBlocksType.cx
@@ -6,10 +6,10 @@ from classiq.interface.generator.arith.register_user_input import RegisterArithm
6
6
  RegisterOrConst = Union[RegisterArithmeticInfo, float]
7
7
 
8
8
 
9
- def fraction_places(argument: RegisterOrConst) -> int:
9
+ def fraction_places(argument: RegisterOrConst, *, machine_precision: int) -> int:
10
10
  if isinstance(argument, RegisterArithmeticInfo):
11
11
  return argument.fraction_places
12
- return number_utils.fraction_places(argument)
12
+ return number_utils.fraction_places(argument, machine_precision=machine_precision)
13
13
 
14
14
 
15
15
  def integer_part_size(argument: RegisterOrConst) -> int:
@@ -18,10 +18,10 @@ def integer_part_size(argument: RegisterOrConst) -> int:
18
18
  return number_utils.integer_part_size(argument)
19
19
 
20
20
 
21
- def size(argument: RegisterOrConst) -> int:
21
+ def size(argument: RegisterOrConst, *, machine_precision: int) -> int:
22
22
  if isinstance(argument, RegisterArithmeticInfo):
23
23
  return argument.size
24
- return number_utils.size(argument)
24
+ return number_utils.size(argument, machine_precision=machine_precision)
25
25
 
26
26
 
27
27
  def is_signed(argument: RegisterOrConst) -> bool:
@@ -75,6 +75,7 @@ class Arithmetic(ArithmeticExpressionABC):
75
75
  def get_arithmetic_params(
76
76
  expr_str: str,
77
77
  var_types: Dict[str, QuantumType],
78
+ machine_precision: int,
78
79
  enable_target: bool = False,
79
80
  ) -> Arithmetic:
80
81
  return Arithmetic(
@@ -86,13 +87,14 @@ def get_arithmetic_params(
86
87
  inputs_to_save=set(var_types.keys()),
87
88
  # FIXME: generalize inout target to multiple qubits
88
89
  target=RegisterArithmeticInfo(size=1) if enable_target else None,
90
+ machine_precision=machine_precision,
89
91
  )
90
92
 
91
93
 
92
94
  def compute_arithmetic_result_type(
93
- expr_str: str, var_types: Dict[str, QuantumType]
95
+ expr_str: str, var_types: Dict[str, QuantumType], machine_precision: int
94
96
  ) -> QuantumType:
95
- arith_param = get_arithmetic_params(expr_str, var_types)
97
+ arith_param = get_arithmetic_params(expr_str, var_types, machine_precision)
96
98
  return register_info_to_quantum_type(
97
99
  arith_param.outputs[ARITHMETIC_EXPRESSION_RESULT_NAME]
98
100
  )
@@ -10,11 +10,15 @@ from classiq.interface.generator.arith.binary_ops import BOOLEAN_OP_WITH_FRACTIO
10
10
 
11
11
  from classiq.exceptions import ClassiqArithmeticError
12
12
 
13
- ArgTypeValidator: TypeAlias = Callable[[List[RegisterOrConst]], None]
13
+ ArgTypeValidator: TypeAlias = Callable[[List[RegisterOrConst], int], None]
14
14
 
15
15
 
16
- def _validate_bitwise_op_args(args: List[RegisterOrConst]) -> None:
17
- if any(fraction_places(arg) > 0 for arg in args):
16
+ def _validate_bitwise_op_args(
17
+ args: List[RegisterOrConst], machine_precision: int
18
+ ) -> None:
19
+ if any(
20
+ fraction_places(arg, machine_precision=machine_precision) > 0 for arg in args
21
+ ):
18
22
  raise ClassiqArithmeticError(BOOLEAN_OP_WITH_FRACTIONS_ERROR)
19
23
 
20
24
 
@@ -25,7 +29,9 @@ arg_type_validator_map: Dict[str, ArgTypeValidator] = dict(
25
29
  )
26
30
 
27
31
 
28
- def validate_operation_arg_types(operation: str, args: List[RegisterOrConst]) -> None:
32
+ def validate_operation_arg_types(
33
+ operation: str, args: List[RegisterOrConst], machine_precision: int
34
+ ) -> None:
29
35
  if operation not in arg_type_validator_map:
30
36
  return
31
- arg_type_validator_map[operation](args)
37
+ arg_type_validator_map[operation](args, machine_precision)
@@ -18,7 +18,8 @@ from classiq.interface.generator.arith.ast_node_rewrite import (
18
18
 
19
19
  from classiq.exceptions import ClassiqArithmeticError
20
20
 
21
- _ILLEGAL_PARSED_GRAPH_ERROR_MESSAGE: str = "parsed graph contains multiple result nodes"
21
+ _MULTIPLE_RESULTS_ERROR_MESSAGE: str = "Expression cannot contain multiple result"
22
+ _TRIVIAL_ARITHMETIC_ERROR_MESSAGE: str = "Expression must be nontrivial"
22
23
  _ALLOWED_MULTI_ARGUMENT_FUNCTIONS = ("min", "max")
23
24
  Node = Union[str, float, int]
24
25
 
@@ -116,8 +117,12 @@ class InDegreeLimiter:
116
117
  for node in list(graph.nodes):
117
118
  if cls._condition(graph, node):
118
119
  graph = cls._node_conversion(graph, node)
119
- if num_of_result_nodes(graph) != 1:
120
- raise ClassiqArithmeticError(_ILLEGAL_PARSED_GRAPH_ERROR_MESSAGE)
120
+
121
+ num_results = sum(int(graph.out_degree(node) == 0) for node in graph.nodes)
122
+ if num_results > 1:
123
+ raise ClassiqArithmeticError(_MULTIPLE_RESULTS_ERROR_MESSAGE)
124
+ elif num_results == 0:
125
+ raise ClassiqArithmeticError(_TRIVIAL_ARITHMETIC_ERROR_MESSAGE)
121
126
  return graph
122
127
 
123
128
 
@@ -134,7 +139,3 @@ def parse_expression(
134
139
  visitor.validate(expression)
135
140
  InDegreeLimiter.graph_conversion(graph=visitor.graph)
136
141
  return visitor.graph
137
-
138
-
139
- def num_of_result_nodes(graph: nx.DiGraph) -> int:
140
- return sum(int(graph.out_degree(node) == 0) for node in graph.nodes)
@@ -5,6 +5,7 @@ from typing import ClassVar, Iterable, Optional, Tuple
5
5
 
6
6
  import pydantic
7
7
 
8
+ from classiq.interface.generator.arith import argument_utils, number_utils
8
9
  from classiq.interface.generator.arith.register_user_input import RegisterArithmeticInfo
9
10
  from classiq.interface.generator.function_params import FunctionParams
10
11
 
@@ -13,6 +14,7 @@ DEFAULT_GARBAGE_OUT_NAME: str = "extra_qubits"
13
14
 
14
15
  class ArithmeticOperationParams(FunctionParams):
15
16
  output_size: Optional[pydantic.PositiveInt]
17
+ machine_precision: pydantic.PositiveInt = number_utils.MAX_FRACTION_PLACES
16
18
  output_name: ClassVar[str]
17
19
  garbage_output_name: ClassVar[str] = DEFAULT_GARBAGE_OUT_NAME
18
20
  _result_register: Optional[RegisterArithmeticInfo] = pydantic.PrivateAttr(
@@ -44,6 +46,11 @@ class ArithmeticOperationParams(FunctionParams):
44
46
  return suggested_bounds
45
47
  return None
46
48
 
49
+ def _compute_fraction_places(self, argument: argument_utils.RegisterOrConst) -> int:
50
+ return argument_utils.fraction_places(
51
+ argument, machine_precision=self.machine_precision
52
+ )
53
+
47
54
  @abc.abstractmethod
48
55
  def get_params_inplace_options(self) -> Iterable[ArithmeticOperationParams]:
49
56
  pass