classiq 0.40.0__py3-none-any.whl → 0.41.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 (81) hide show
  1. classiq/__init__.py +4 -2
  2. classiq/_internals/api_wrapper.py +3 -21
  3. classiq/applications/chemistry/chemistry_model_constructor.py +86 -100
  4. classiq/applications/combinatorial_helpers/combinatorial_problem_utils.py +6 -24
  5. classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +33 -45
  6. classiq/applications/combinatorial_optimization/__init__.py +2 -0
  7. classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +29 -26
  8. classiq/applications/finance/finance_model_constructor.py +23 -26
  9. classiq/applications/grover/grover_model_constructor.py +37 -38
  10. classiq/applications/qsvm/qsvm.py +1 -2
  11. classiq/applications/qsvm/qsvm_model_constructor.py +15 -16
  12. classiq/execution/__init__.py +4 -0
  13. classiq/execution/execution_session.py +151 -0
  14. classiq/execution/qnn.py +80 -0
  15. classiq/executor.py +2 -109
  16. classiq/interface/_version.py +1 -1
  17. classiq/interface/analyzer/analysis_params.py +11 -0
  18. classiq/interface/applications/qsvm.py +0 -8
  19. classiq/interface/ast_node.py +12 -2
  20. classiq/interface/backend/backend_preferences.py +25 -1
  21. classiq/interface/backend/quantum_backend_providers.py +4 -4
  22. classiq/interface/executor/execution_preferences.py +4 -59
  23. classiq/interface/executor/execution_result.py +22 -1
  24. classiq/interface/generator/arith/arithmetic_expression_validator.py +0 -2
  25. classiq/interface/generator/arith/binary_ops.py +88 -25
  26. classiq/interface/generator/arith/unary_ops.py +28 -19
  27. classiq/interface/generator/expressions/atomic_expression_functions.py +6 -2
  28. classiq/interface/generator/expressions/enums/__init__.py +10 -0
  29. classiq/interface/generator/expressions/enums/classical_enum.py +5 -1
  30. classiq/interface/generator/expressions/expression.py +9 -2
  31. classiq/interface/generator/expressions/qmod_qarray_proxy.py +7 -0
  32. classiq/interface/generator/expressions/qmod_qscalar_proxy.py +0 -1
  33. classiq/interface/generator/expressions/sympy_supported_expressions.py +10 -1
  34. classiq/interface/generator/functions/builtins/internal_operators.py +7 -62
  35. classiq/interface/generator/functions/builtins/open_lib_functions.py +810 -2
  36. classiq/interface/generator/functions/classical_type.py +1 -3
  37. classiq/interface/generator/synthesis_metadata/synthesis_duration.py +0 -4
  38. classiq/interface/model/bind_operation.py +3 -1
  39. classiq/interface/model/call_synthesis_data.py +2 -13
  40. classiq/interface/model/classical_if.py +3 -1
  41. classiq/interface/model/classical_parameter_declaration.py +13 -0
  42. classiq/interface/model/control.py +3 -101
  43. classiq/interface/model/inplace_binary_operation.py +3 -1
  44. classiq/interface/model/invert.py +3 -1
  45. classiq/interface/model/port_declaration.py +8 -1
  46. classiq/interface/model/power.py +3 -1
  47. classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +4 -2
  48. classiq/interface/model/quantum_expressions/arithmetic_operation.py +3 -1
  49. classiq/interface/model/quantum_expressions/quantum_expression.py +11 -1
  50. classiq/interface/model/quantum_function_call.py +4 -10
  51. classiq/interface/model/quantum_function_declaration.py +26 -4
  52. classiq/interface/model/quantum_lambda_function.py +1 -20
  53. classiq/interface/model/quantum_statement.py +9 -2
  54. classiq/interface/model/repeat.py +3 -1
  55. classiq/interface/model/statement_block.py +19 -13
  56. classiq/interface/model/validations/handles_validator.py +8 -2
  57. classiq/interface/model/variable_declaration_statement.py +3 -1
  58. classiq/interface/model/within_apply_operation.py +3 -1
  59. classiq/interface/server/routes.py +0 -5
  60. classiq/qmod/__init__.py +1 -2
  61. classiq/qmod/builtins/classical_execution_primitives.py +22 -2
  62. classiq/qmod/builtins/functions.py +51 -1
  63. classiq/qmod/builtins/operations.py +6 -36
  64. classiq/qmod/declaration_inferrer.py +8 -15
  65. classiq/qmod/native/__init__.py +9 -0
  66. classiq/qmod/native/expression_to_qmod.py +12 -9
  67. classiq/qmod/native/pretty_printer.py +4 -4
  68. classiq/qmod/pretty_print/__init__.py +9 -0
  69. classiq/qmod/pretty_print/expression_to_python.py +221 -0
  70. classiq/qmod/pretty_print/pretty_printer.py +421 -0
  71. classiq/qmod/qmod_parameter.py +7 -4
  72. classiq/qmod/quantum_callable.py +2 -1
  73. classiq/qmod/quantum_expandable.py +4 -3
  74. classiq/qmod/quantum_function.py +4 -16
  75. classiq/qmod/symbolic.py +1 -6
  76. classiq/synthesis.py +15 -16
  77. {classiq-0.40.0.dist-info → classiq-0.41.0.dist-info}/METADATA +5 -4
  78. {classiq-0.40.0.dist-info → classiq-0.41.0.dist-info}/RECORD +79 -76
  79. classiq/interface/model/common_model_types.py +0 -23
  80. classiq/interface/model/quantum_expressions/control_state.py +0 -38
  81. {classiq-0.40.0.dist-info → classiq-0.41.0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,80 @@
1
+ import functools
2
+ from typing import List, Optional
3
+
4
+ import more_itertools
5
+
6
+ from classiq.interface.chemistry.operator import PauliOperator
7
+ from classiq.interface.executor.execution_result import (
8
+ ResultsCollection,
9
+ SavedResultValueType,
10
+ TaggedEstimationResult,
11
+ TaggedExecutionDetails,
12
+ )
13
+ from classiq.interface.executor.quantum_code import Arguments, MultipleArguments
14
+
15
+ from classiq.applications.combinatorial_helpers.pauli_helpers.pauli_utils import (
16
+ pauli_operator_to_hamiltonian,
17
+ )
18
+ from classiq.execution.execution_session import ExecutionSession
19
+ from classiq.executor import DEFAULT_RESULT_NAME
20
+ from classiq.synthesis import SerializedQuantumProgram
21
+
22
+ _MAX_ARGUMENTS_SIZE = 1024
23
+
24
+
25
+ def _execute_qnn_estimate(
26
+ session: ExecutionSession,
27
+ arguments: List[Arguments],
28
+ observable: PauliOperator,
29
+ ) -> ResultsCollection:
30
+ hamiltonian = pauli_operator_to_hamiltonian(observable.pauli_list)
31
+ return [
32
+ TaggedEstimationResult(
33
+ name=DEFAULT_RESULT_NAME,
34
+ value=result,
35
+ value_type=SavedResultValueType.EstimationResult,
36
+ )
37
+ for result in session.batch_estimate(
38
+ hamiltonian=hamiltonian, parameters=arguments
39
+ )
40
+ ]
41
+
42
+
43
+ def _execute_qnn_sample(
44
+ session: ExecutionSession,
45
+ arguments: List[Arguments],
46
+ ) -> ResultsCollection:
47
+ return [
48
+ TaggedExecutionDetails(
49
+ name=DEFAULT_RESULT_NAME,
50
+ value=result,
51
+ value_type=SavedResultValueType.ExecutionDetails,
52
+ )
53
+ for result in session.batch_sample(arguments)
54
+ ]
55
+
56
+
57
+ def execute_qnn(
58
+ quantum_program: SerializedQuantumProgram,
59
+ arguments: MultipleArguments,
60
+ observable: Optional[PauliOperator] = None,
61
+ ) -> ResultsCollection:
62
+ session = ExecutionSession(quantum_program)
63
+
64
+ if observable:
65
+ execute_function = functools.partial(
66
+ _execute_qnn_estimate,
67
+ session=session,
68
+ observable=observable,
69
+ )
70
+ else:
71
+ execute_function = functools.partial(
72
+ _execute_qnn_sample,
73
+ session=session,
74
+ )
75
+
76
+ result: ResultsCollection = []
77
+ for chunk in more_itertools.chunked(arguments, _MAX_ARGUMENTS_SIZE):
78
+ chunk_result = execute_function(arguments=chunk)
79
+ result.extend(chunk_result)
80
+ return result
classiq/executor.py CHANGED
@@ -1,27 +1,13 @@
1
1
  """Executor module, implementing facilities for executing quantum programs using Classiq platform."""
2
2
 
3
- import functools
4
- from typing import Optional, Tuple, Union
3
+ from typing import Tuple, Union
5
4
 
6
- import more_itertools
7
5
  from typing_extensions import TypeAlias
8
6
 
9
7
  from classiq.interface.backend.backend_preferences import BackendPreferencesTypes
10
- from classiq.interface.chemistry.operator import PauliOperators
11
8
  from classiq.interface.executor.estimation import OperatorsEstimation
12
9
  from classiq.interface.executor.execution_preferences import ExecutionPreferences
13
- from classiq.interface.executor.execution_request import (
14
- EstimateOperatorsExecution,
15
- ExecutionRequest,
16
- QuantumCodeExecution,
17
- )
18
- from classiq.interface.executor.execution_result import (
19
- ResultsCollection,
20
- SavedResultValueType,
21
- TaggedEstimationResult,
22
- TaggedExecutionDetails,
23
- )
24
- from classiq.interface.executor.quantum_code import MultipleArguments, QuantumCode
10
+ from classiq.interface.executor.quantum_code import QuantumCode
25
11
  from classiq.interface.executor.quantum_instruction_set import QuantumInstructionSet
26
12
  from classiq.interface.executor.result import ExecutionDetails
27
13
  from classiq.interface.generator.quantum_program import QuantumProgram
@@ -38,7 +24,6 @@ ProgramAndResult: TypeAlias = Tuple[QuantumCode, BatchExecutionResult]
38
24
  BackendPreferencesAndResult: TypeAlias = Tuple[
39
25
  BackendPreferencesTypes, int, BatchExecutionResult
40
26
  ]
41
- _MAX_ARGUMENTS_SIZE = 1024
42
27
 
43
28
 
44
29
  def _parse_serialized_qprog(
@@ -56,83 +41,6 @@ async def execute_async(quantum_program: SerializedQuantumProgram) -> ExecutionJ
56
41
  execute = syncify_function(execute_async)
57
42
 
58
43
 
59
- async def _execute_qnn_async_estimate(
60
- quantum_program: QuantumCode,
61
- execution_preferences: ExecutionPreferences,
62
- observables: PauliOperators,
63
- ) -> ResultsCollection:
64
- request = ExecutionRequest(
65
- execution_payload=EstimateOperatorsExecution(
66
- quantum_program=quantum_program,
67
- operators=observables,
68
- ),
69
- preferences=execution_preferences,
70
- )
71
-
72
- results = await ApiWrapper.call_execute_estimate(request)
73
- return [
74
- TaggedEstimationResult(
75
- name=DEFAULT_RESULT_NAME,
76
- value=result,
77
- value_type=SavedResultValueType.EstimationResult,
78
- )
79
- for result in results
80
- ]
81
-
82
-
83
- async def _execute_qnn_async_program(
84
- quantum_program: QuantumCode,
85
- execution_preferences: ExecutionPreferences,
86
- ) -> ResultsCollection:
87
- request = ExecutionRequest(
88
- execution_payload=QuantumCodeExecution(**quantum_program.dict()),
89
- preferences=execution_preferences,
90
- )
91
-
92
- api_result = await ApiWrapper.call_execute_quantum_program(request)
93
- return [
94
- TaggedExecutionDetails(
95
- name=DEFAULT_RESULT_NAME,
96
- value=result,
97
- value_type=SavedResultValueType.ExecutionDetails,
98
- )
99
- for result in api_result.details
100
- ]
101
-
102
-
103
- async def execute_qnn_async(
104
- quantum_program: SerializedQuantumProgram,
105
- arguments: MultipleArguments,
106
- observables: Optional[PauliOperators] = None,
107
- ) -> ResultsCollection:
108
- circuit = _parse_serialized_qprog(quantum_program)
109
- execution_preferences = circuit.model.execution_preferences
110
-
111
- legacy_quantum_program = circuit.to_program()
112
-
113
- if observables:
114
- execute_function = functools.partial(
115
- _execute_qnn_async_estimate,
116
- execution_preferences=execution_preferences,
117
- observables=observables,
118
- )
119
- else:
120
- execute_function = functools.partial(
121
- _execute_qnn_async_program,
122
- execution_preferences=execution_preferences,
123
- )
124
-
125
- result: ResultsCollection = []
126
- for chunk in more_itertools.chunked(arguments, _MAX_ARGUMENTS_SIZE):
127
- legacy_quantum_program.arguments = tuple(chunk)
128
- chunk_result = await execute_function(quantum_program=legacy_quantum_program)
129
- result.extend(chunk_result)
130
- return result
131
-
132
-
133
- execute_qnn = syncify_function(execute_qnn_async)
134
-
135
-
136
44
  def set_quantum_program_execution_preferences(
137
45
  quantum_program: SerializedQuantumProgram,
138
46
  preferences: ExecutionPreferences,
@@ -142,24 +50,9 @@ def set_quantum_program_execution_preferences(
142
50
  return SerializedQuantumProgram(circuit.json())
143
51
 
144
52
 
145
- def set_initial_values(
146
- quantum_program: SerializedQuantumProgram,
147
- **kwargs: int,
148
- ) -> SerializedQuantumProgram:
149
- circuit = _parse_serialized_qprog(quantum_program)
150
- circuit.initial_values = kwargs
151
-
152
- # Validate the initial values by calling `get_registers_initialization`
153
- circuit.get_registers_initialization(circuit.initial_values)
154
-
155
- return SerializedQuantumProgram(circuit.json())
156
-
157
-
158
53
  __all__ = [
159
54
  "QuantumCode",
160
55
  "QuantumInstructionSet",
161
- "execute_qnn",
162
56
  "OperatorsEstimation",
163
57
  "set_quantum_program_execution_preferences",
164
- "set_initial_values",
165
58
  ]
@@ -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.40.0'
6
+ SEMVER_VERSION = '0.41.0'
7
7
  VERSION = str(Version(SEMVER_VERSION))
@@ -44,6 +44,17 @@ class AnalysisOptionalDevicesParams(HardwareListParams):
44
44
  )
45
45
 
46
46
 
47
+ class GateNamsMapping(pydantic.BaseModel):
48
+ qasm_name: str
49
+ display_name: str
50
+
51
+
52
+ class LatexParams(AnalysisParams):
53
+ gate_names: List[GateNamsMapping] = pydantic.Field(
54
+ default=..., description="List of gate names as apper in the qasm"
55
+ )
56
+
57
+
47
58
  class AnalysisHardwareTranspilationParams(pydantic.BaseModel):
48
59
  hardware_data: Optional[SynthesisHardwareData]
49
60
  random_seed: int
@@ -12,12 +12,10 @@ from typing import (
12
12
  import numpy as np
13
13
  import pydantic
14
14
  from numpy.typing import ArrayLike
15
- from pydantic import BaseModel
16
15
 
17
16
  if TYPE_CHECKING:
18
17
  from pydantic.typing import AnyClassMethod
19
18
 
20
- from classiq.interface.executor.execution_preferences import ExecutionPreferences
21
19
  from classiq.interface.helpers.versioned_model import VersionedModel
22
20
 
23
21
  DataList = List[List[float]]
@@ -35,11 +33,6 @@ def listify(obj: Union[IterableType, ArrayLike]) -> list:
35
33
  return list(obj) # type: ignore[arg-type]
36
34
 
37
35
 
38
- class QSVMPreferences(BaseModel):
39
- execution_preferences: ExecutionPreferences
40
- l2_norm_regularization_factor: float = 0.001
41
-
42
-
43
36
  def validate_array_to_list(name: str) -> "AnyClassMethod":
44
37
  return pydantic.validator(name, pre=True, allow_reuse=True)(listify)
45
38
 
@@ -96,7 +89,6 @@ class QSVMData(VersionedModel):
96
89
  data: DataList
97
90
  labels: Optional[LabelsInt] = None
98
91
  internal_state: Optional[QSVMInternalState] = None
99
- preferences: QSVMPreferences
100
92
 
101
93
  class Config:
102
94
  smart_union = True
@@ -1,3 +1,4 @@
1
+ import os
1
2
  from typing import Optional
2
3
 
3
4
  import pydantic
@@ -7,15 +8,24 @@ from classiq.interface.helpers.hashable_pydantic_base_model import (
7
8
  )
8
9
 
9
10
 
10
- class SourceReference(pydantic.BaseModel):
11
+ class SourceReference(HashablePydanticBaseModel):
11
12
  start_line: int
12
13
  start_column: int
13
14
  end_line: int
14
15
  end_column: int
15
16
  file_name: Optional[str] = pydantic.Field(default=None)
16
17
 
18
+ def __str__(self) -> str:
19
+ file_string = (
20
+ f"file {os.path.basename(self.file_name)} " if self.file_name else ""
21
+ )
22
+ start_character_string = (
23
+ f" character {self.start_column}" if self.start_column else ""
24
+ )
25
+ return f"{file_string}line {self.start_line}{start_character_string}"
17
26
 
18
- class ASTNode(pydantic.BaseModel):
27
+
28
+ class ASTNode(HashablePydanticBaseModel):
19
29
  source_ref: Optional[SourceReference] = pydantic.Field(default=None)
20
30
 
21
31
 
@@ -4,7 +4,7 @@ from datetime import timedelta
4
4
  from typing import Any, Dict, Iterable, List, Optional, Union
5
5
 
6
6
  import pydantic
7
- from pydantic import BaseModel, validator
7
+ from pydantic import BaseModel, PrivateAttr, validator
8
8
 
9
9
  from classiq.interface.backend import pydantic_backend
10
10
  from classiq.interface.backend.quantum_backend_providers import (
@@ -61,9 +61,22 @@ AWS_DEFAULT_JOB_TIMEOUT_SECONDS = int(timedelta(minutes=240).total_seconds())
61
61
 
62
62
  class AliceBobBackendPreferences(BackendPreferences):
63
63
  backend_service_provider: ProviderTypeVendor.ALICE_BOB
64
+ distance: Optional[int] = pydantic.Field(
65
+ default=None, description="Repetition code distance"
66
+ )
67
+ kappa_1: Optional[float] = pydantic.Field(
68
+ default=None, description="One-photon dissipation rate (Hz)"
69
+ )
70
+ kappa_2: Optional[float] = pydantic.Field(
71
+ default=None, description="Two-photon dissipation rate (Hz)"
72
+ )
73
+ average_nb_photons: Optional[float] = pydantic.Field(
74
+ default=None, description="Average number of photons"
75
+ )
64
76
  api_key: pydantic_backend.PydanticAliceBobApiKeyType = pydantic.Field(
65
77
  ..., description="AliceBob API key"
66
78
  )
79
+ _parameters: Dict[str, Any] = PrivateAttr(default_factory=dict)
67
80
 
68
81
  @pydantic.root_validator(pre=True)
69
82
  def _set_backend_service_provider(cls, values: Dict[str, Any]) -> Dict[str, Any]:
@@ -71,6 +84,17 @@ class AliceBobBackendPreferences(BackendPreferences):
71
84
  values, "backend_service_provider", ProviderVendor.ALICE_AND_BOB
72
85
  )
73
86
 
87
+ @property
88
+ def parameters(self) -> Dict[str, Any]:
89
+ self._parameters = {
90
+ "distance": self.distance,
91
+ "kappa_1": self.kappa_1,
92
+ "kappa_2": self.kappa_2,
93
+ "average_nb_photons": self.average_nb_photons,
94
+ }
95
+ self._parameters = {k: v for k, v in self._parameters.items() if v is not None}
96
+ return self._parameters
97
+
74
98
 
75
99
  class ClassiqBackendPreferences(BackendPreferences):
76
100
  backend_service_provider: ProviderTypeVendor.CLASSIQ
@@ -149,10 +149,10 @@ class GoogleNvidiaBackendNames(StrEnum):
149
149
 
150
150
 
151
151
  class AliceBobBackendNames(StrEnum):
152
- PERFECT_QUBITS = "EMU:20Q:PERFECT_QUBITS"
153
- LOGICAL_TARGET = "EMU:40Q:LOGICAL_TARGET"
154
- LOGICAL_EARLY = "EMU:15Q:LOGICAL_EARLY"
155
- TRANSMONS = "EMU:7Q:TRANSMONS"
152
+ PERFECT_QUBITS = "PERFECT_QUBITS"
153
+ LOGICAL_TARGET = "LOGICAL_TARGET"
154
+ LOGICAL_EARLY = "LOGICAL_EARLY"
155
+ TRANSMONS = "TRANSMONS"
156
156
 
157
157
 
158
158
  class OQCBackendNames(StrEnum):
@@ -1,5 +1,5 @@
1
1
  from datetime import timedelta
2
- from typing import Any, Dict, Optional, TypeVar
2
+ from typing import Any, Dict, Optional
3
3
 
4
4
  import pydantic
5
5
 
@@ -13,10 +13,7 @@ from classiq.interface.backend.pydantic_backend import MAX_EXECUTION_TIMEOUT_SEC
13
13
  from classiq.interface.backend.quantum_backend_providers import (
14
14
  ClassiqSimulatorBackendNames,
15
15
  )
16
- from classiq.interface.executor.optimizer_preferences import (
17
- OptimizerPreferences,
18
- OptimizerType,
19
- )
16
+ from classiq.interface.executor.optimizer_preferences import OptimizerType
20
17
  from classiq.interface.generator.model.preferences.preferences import (
21
18
  TranspilationOption,
22
19
  )
@@ -48,15 +45,11 @@ class ExecutionPreferences(pydantic.BaseModel):
48
45
  description="If set, limits the execution runtime. Value is in seconds. "
49
46
  "Not supported on all platforms.",
50
47
  )
51
- optimizer_preferences: Optional[OptimizerPreferences] = pydantic.Field(
52
- default_factory=None,
53
- description="Settings related to VQE execution.",
54
- )
55
48
  noise_properties: Optional[NoiseProperties] = pydantic.Field(
56
49
  default=None, description="Properties of the noise in the circuit"
57
50
  )
58
51
  random_seed: int = pydantic.Field(
59
- default=None,
52
+ default_factory=create_random_seed,
60
53
  description="The random seed used for the execution",
61
54
  )
62
55
  backend_preferences: BackendPreferencesTypes = backend_preferences_field(
@@ -76,14 +69,6 @@ class ExecutionPreferences(pydantic.BaseModel):
76
69
  def __init__(self, **kwargs: Any) -> None:
77
70
  super().__init__(**kwargs)
78
71
 
79
- @pydantic.validator("num_shots", always=True)
80
- def validate_num_shots(
81
- cls, original_num_shots: Optional[pydantic.PositiveInt], values: Dict[str, Any]
82
- ) -> Optional[pydantic.PositiveInt]:
83
- return _choose_original_or_optimizer_attribute(
84
- original_num_shots, "num_shots", None, values
85
- )
86
-
87
72
  @pydantic.validator("backend_preferences", always=True)
88
73
  def validate_timeout_for_aws(
89
74
  cls, backend_preferences: BackendPreferencesTypes, values: Dict[str, Any]
@@ -105,50 +90,10 @@ class ExecutionPreferences(pydantic.BaseModel):
105
90
  backend_preferences.job_timeout = timeout
106
91
  return backend_preferences
107
92
 
108
- @pydantic.validator("random_seed", always=True)
109
- def validate_random_seed(
110
- cls, original_random_seed: Optional[int], values: Dict[str, Any]
111
- ) -> int:
112
- return _choose_original_or_optimizer_attribute(
113
- original_random_seed, "random_seed", create_random_seed(), values
114
- )
115
-
116
-
117
- T = TypeVar("T")
118
-
119
-
120
- def _choose_original_or_optimizer_attribute(
121
- original_attribute: Optional[T],
122
- attribure_name: str,
123
- default_value: T,
124
- values: Dict[str, Any],
125
- ) -> T:
126
- optimizer_preferences = values.get("optimizer_preferences", None)
127
- optimizer_attribute = getattr(optimizer_preferences, attribure_name, None)
128
-
129
- if original_attribute is None and optimizer_attribute is None:
130
- return default_value
131
-
132
- elif optimizer_attribute is None:
133
- # mypy doesn't understand that original_attribute is not None
134
- return original_attribute # type: ignore[return-value]
135
-
136
- elif original_attribute is None:
137
- return optimizer_attribute
138
-
139
- elif original_attribute != optimizer_attribute:
140
- raise ClassiqValueError(
141
- f"Different {attribure_name} were given for ExecutionPreferences and OptimizerPreferences."
142
- )
143
-
144
- else: # This case is original_num_shots == optimizer_num_shots != None
145
- return original_attribute
146
-
147
93
 
148
94
  __all__ = [
149
95
  "ExecutionPreferences",
150
- "NoiseProperties",
151
- "OptimizerPreferences",
152
96
  "OptimizerType",
97
+ "NoiseProperties",
153
98
  "QaeWithQpeEstimationMethod",
154
99
  ]
@@ -4,7 +4,12 @@ from pydantic import BaseModel, Field
4
4
  from typing_extensions import Annotated, TypeAlias
5
5
 
6
6
  from classiq.interface.executor.iqae_result import IQAEResult
7
- from classiq.interface.executor.result import EstimationResult, ExecutionDetails
7
+ from classiq.interface.executor.result import (
8
+ EstimationResult,
9
+ EstimationResults,
10
+ ExecutionDetails,
11
+ MultipleExecutionDetails,
12
+ )
8
13
  from classiq.interface.executor.vqe_result import VQESolverResult
9
14
  from classiq.interface.helpers.versioned_model import VersionedModel
10
15
 
@@ -17,7 +22,9 @@ class SavedResultValueType(StrEnum):
17
22
  Boolean = "bool"
18
23
  VQESolverResult = "VQESolverResult"
19
24
  ExecutionDetails = "ExecutionDetails"
25
+ MultipleExecutionDetails = "MultipleExecutionDetails"
20
26
  EstimationResult = "EstimationResult"
27
+ EstimationResults = "EstimationResults"
21
28
  IQAEResult = "IQAEResult"
22
29
  Unstructured = "Unstructured"
23
30
 
@@ -52,12 +59,24 @@ class TaggedExecutionDetails(BaseModel):
52
59
  value: ExecutionDetails
53
60
 
54
61
 
62
+ class TaggedMultipleExecutionDetails(BaseModel):
63
+ value_type: Literal[SavedResultValueType.MultipleExecutionDetails]
64
+ name: str
65
+ value: MultipleExecutionDetails
66
+
67
+
55
68
  class TaggedEstimationResult(BaseModel):
56
69
  value_type: Literal[SavedResultValueType.EstimationResult]
57
70
  name: str
58
71
  value: EstimationResult
59
72
 
60
73
 
74
+ class TaggedEstimationResults(BaseModel):
75
+ value_type: Literal[SavedResultValueType.EstimationResults]
76
+ name: str
77
+ value: EstimationResults
78
+
79
+
61
80
  class TaggedIQAEResult(BaseModel):
62
81
  value_type: Literal[SavedResultValueType.IQAEResult]
63
82
  name: str
@@ -77,7 +96,9 @@ SavedResult = Annotated[
77
96
  TaggedBoolean,
78
97
  TaggedVQESolverResult,
79
98
  TaggedExecutionDetails,
99
+ TaggedMultipleExecutionDetails,
80
100
  TaggedEstimationResult,
101
+ TaggedEstimationResults,
81
102
  TaggedIQAEResult,
82
103
  TaggedUnstructured,
83
104
  ],
@@ -10,7 +10,6 @@ from classiq.interface.generator.arith.ast_node_rewrite import AstNodeRewrite
10
10
  from classiq.interface.generator.expressions.sympy_supported_expressions import (
11
11
  SYMPY_SUPPORTED_EXPRESSIONS,
12
12
  )
13
- from classiq.interface.generator.functions.classical_type import CLASSICAL_ATTRIBUTES
14
13
 
15
14
  from classiq.exceptions import ClassiqArithmeticError, ClassiqValueError
16
15
 
@@ -175,7 +174,6 @@ class ExpressionValidator(ast.NodeVisitor):
175
174
  if not (
176
175
  isinstance(node.value, ast.Name)
177
176
  and node.value.id in self._supported_attr_values
178
- or node.attr in CLASSICAL_ATTRIBUTES.keys()
179
177
  ):
180
178
  raise ClassiqValueError(
181
179
  f"Attribute is not supported for value {node.value}"