classiq 0.39.0__py3-none-any.whl → 0.40.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 (51) hide show
  1. classiq/__init__.py +1 -0
  2. classiq/applications/chemistry/chemistry_model_constructor.py +1 -1
  3. classiq/applications/combinatorial_helpers/combinatorial_problem_utils.py +5 -6
  4. classiq/applications/combinatorial_helpers/optimization_model.py +7 -6
  5. classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +0 -10
  6. classiq/applications/combinatorial_optimization/__init__.py +2 -0
  7. classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +2 -2
  8. classiq/interface/_version.py +1 -1
  9. classiq/interface/backend/backend_preferences.py +5 -5
  10. classiq/interface/backend/quantum_backend_providers.py +7 -7
  11. classiq/interface/executor/execution_preferences.py +4 -9
  12. classiq/interface/generator/application_apis/chemistry_declarations.py +2 -4
  13. classiq/interface/generator/application_apis/finance_declarations.py +1 -1
  14. classiq/interface/generator/arith/arithmetic_expression_validator.py +2 -0
  15. classiq/interface/generator/expressions/qmod_qarray_proxy.py +82 -0
  16. classiq/interface/generator/expressions/qmod_qscalar_proxy.py +21 -0
  17. classiq/interface/generator/expressions/qmod_sized_proxy.py +22 -0
  18. classiq/interface/generator/functions/builtins/core_library/atomic_quantum_functions.py +8 -6
  19. classiq/interface/generator/functions/builtins/core_library/exponentiation_functions.py +10 -4
  20. classiq/interface/generator/functions/builtins/open_lib_functions.py +624 -76
  21. classiq/interface/generator/functions/classical_type.py +29 -17
  22. classiq/interface/generator/model/preferences/preferences.py +4 -2
  23. classiq/interface/model/control.py +104 -8
  24. classiq/interface/model/quantum_type.py +6 -5
  25. classiq/interface/model/resolvers/function_call_resolver.py +0 -5
  26. classiq/interface/model/statement_block.py +1 -4
  27. classiq/qmod/__init__.py +6 -2
  28. classiq/qmod/builtins/classical_functions.py +30 -35
  29. classiq/qmod/builtins/functions.py +213 -153
  30. classiq/qmod/builtins/operations.py +78 -24
  31. classiq/qmod/builtins/structs.py +50 -48
  32. classiq/qmod/declaration_inferrer.py +30 -18
  33. classiq/qmod/native/expression_to_qmod.py +5 -4
  34. classiq/qmod/native/pretty_printer.py +7 -14
  35. classiq/qmod/qmod_constant.py +7 -7
  36. classiq/qmod/qmod_parameter.py +54 -33
  37. classiq/qmod/qmod_struct.py +2 -2
  38. classiq/qmod/qmod_variable.py +40 -29
  39. classiq/qmod/quantum_callable.py +7 -4
  40. classiq/qmod/quantum_expandable.py +19 -13
  41. classiq/qmod/quantum_function.py +25 -2
  42. classiq/qmod/symbolic.py +78 -68
  43. classiq/qmod/symbolic_expr.py +1 -1
  44. classiq/qmod/symbolic_type.py +1 -4
  45. classiq/qmod/utilities.py +29 -0
  46. {classiq-0.39.0.dist-info → classiq-0.40.0.dist-info}/METADATA +1 -1
  47. {classiq-0.39.0.dist-info → classiq-0.40.0.dist-info}/RECORD +48 -50
  48. classiq/interface/executor/error_mitigation.py +0 -6
  49. classiq/interface/generator/functions/builtins/core_library/chemistry_functions.py +0 -0
  50. classiq/interface/model/quantum_if_operation.py +0 -94
  51. {classiq-0.39.0.dist-info → classiq-0.40.0.dist-info}/WHEEL +0 -0
classiq/__init__.py CHANGED
@@ -34,6 +34,7 @@ from classiq.applications.chemistry import (
34
34
  )
35
35
  from classiq.applications.combinatorial_optimization import (
36
36
  construct_combinatorial_optimization_model,
37
+ pyo_model_to_hamiltonian,
37
38
  )
38
39
  from classiq.applications.finance import construct_finance_model
39
40
  from classiq.applications.grover import construct_grover_model
@@ -446,7 +446,7 @@ def _get_chemistry_quantum_main(
446
446
  function="allocate",
447
447
  positional_args=[
448
448
  Expression(
449
- expr=f"len(get_field({_get_problem_to_hamiltonian_name(chemistry_problem)}({_convert_library_problem_to_qmod_problem(chemistry_problem)})[0], 'pauli'))"
449
+ expr=f"get_field(get_field({_get_problem_to_hamiltonian_name(chemistry_problem)}({_convert_library_problem_to_qmod_problem(chemistry_problem)})[0], 'pauli'), 'len')"
450
450
  ),
451
451
  HandleBinding(name="qbv"),
452
452
  ],
@@ -9,6 +9,7 @@ from classiq.interface.combinatorial_optimization.solver_types import QSolver
9
9
  from classiq.interface.executor.vqe_result import VQESolverResult
10
10
  from classiq.interface.generator.functions.qmod_python_interface import QmodPyStruct
11
11
 
12
+ from classiq import Pauli
12
13
  from classiq.applications.combinatorial_helpers.optimization_model import (
13
14
  OptimizationModel,
14
15
  )
@@ -16,14 +17,13 @@ from classiq.applications.combinatorial_helpers.pauli_helpers.pauli_sparsing imp
16
17
  SparsePauliOp,
17
18
  )
18
19
  from classiq.applications.combinatorial_helpers.pauli_helpers.pauli_utils import (
19
- PauliTerm,
20
20
  get_pauli_operator,
21
21
  pauli_operator_to_hamiltonian,
22
- pauli_string_to_int,
23
22
  )
24
23
  from classiq.applications.combinatorial_helpers.pyomo_utils import (
25
24
  convert_pyomo_to_global_presentation,
26
25
  )
26
+ from classiq.qmod.builtins import PauliTerm
27
27
 
28
28
 
29
29
  def compute_qaoa_initial_point(
@@ -58,10 +58,9 @@ def pyo_model_to_hamiltonian(
58
58
  pauli_operator = get_pauli_operator(hamiltonian).pauli_list
59
59
  pauli_terms = []
60
60
  for item in pauli_operator:
61
- term = PauliTerm()
62
- term.pauli, term.coefficient = (
63
- pauli_string_to_int(item[0]),
64
- cast(complex, item[1]).real,
61
+ term = PauliTerm(
62
+ [Pauli[p] for p in item[0]], # type:ignore[arg-type]
63
+ cast(complex, item[1]).real, # type:ignore[arg-type]
65
64
  )
66
65
  pauli_terms.append(term)
67
66
 
@@ -45,22 +45,23 @@ class OptimizationModel:
45
45
  encoding_type: Optional[EncodingType] = None,
46
46
  ) -> None:
47
47
  assert model.nobjectives() == 1, "model must have a single objective"
48
- self._model_original = copy.deepcopy(model)
49
- self._assigned_model = remove_fixed_variables(model)
48
+ model_copy = copy.deepcopy(model)
49
+ self._model_original = model
50
+ self._assigned_model = remove_fixed_variables(model_copy)
50
51
  self.qsolver = qsolver
51
52
  self._encoding_type = encoding_type
52
53
 
53
- self.is_encoded = encoding_utils.is_model_encodable(model)
54
+ self.is_encoded = encoding_utils.is_model_encodable(model_copy)
54
55
  if self.is_encoded:
55
56
  if self._encoding_type is None:
56
57
  self._encoding_type = EncodingType.BINARY
57
58
  self._model_encoder = encoding.ModelEncoder(
58
- model, qsolver, self._encoding_type
59
+ model_copy, qsolver, self._encoding_type
59
60
  )
60
61
  self._model = self._model_encoder.encoded_model
61
62
  self._vars_encoding_mapping = self._model_encoder.vars_encoding_mapping
62
63
  else:
63
- self._model = model
64
+ self._model = model_copy
64
65
  # TODO How to handle encoding_type == None
65
66
  self._vars_encoding_mapping = EncodingMapping(self._encoding_type) # type: ignore[arg-type]
66
67
 
@@ -70,7 +71,7 @@ class OptimizationModel:
70
71
  self.vars_not_encoded, self._vars_encoding_mapping
71
72
  )
72
73
 
73
- self.is_maximization = sense.is_maximization(model)
74
+ self.is_maximization = sense.is_maximization(model_copy)
74
75
  self.objective = next(self._model.component_objects(pyo.Objective))
75
76
 
76
77
  self.penalty_energy = penalty_energy
@@ -12,16 +12,6 @@ from classiq.exceptions import (
12
12
  )
13
13
 
14
14
 
15
- class PauliTerm:
16
- pauli: List[int]
17
- coefficient: float
18
-
19
-
20
- def pauli_string_to_int(pauli_str: str) -> List[int]:
21
- pauli_map = {"I": 0, "X": 1, "Y": 2, "Z": 3}
22
- return [pauli_map[char] for char in pauli_str]
23
-
24
-
25
15
  def _pauli_str_to_enums(pauli_str: str) -> str:
26
16
  return ", ".join(f"Pauli.{pauli_term}" for pauli_term in pauli_str)
27
17
 
@@ -6,6 +6,7 @@ from classiq.interface.combinatorial_optimization.solver_types import QSolver
6
6
 
7
7
  from classiq.applications.combinatorial_helpers.combinatorial_problem_utils import (
8
8
  get_optimization_solution_from_pyo,
9
+ pyo_model_to_hamiltonian,
9
10
  )
10
11
 
11
12
  from .combinatorial_optimization_config import OptimizerConfig, QAOAConfig
@@ -21,6 +22,7 @@ __all__ = [
21
22
  "construct_combinatorial_optimization_model",
22
23
  "examples",
23
24
  "get_optimization_solution_from_pyo",
25
+ "pyo_model_to_hamiltonian",
24
26
  ]
25
27
 
26
28
 
@@ -88,14 +88,14 @@ def construct_combi_opt_py_model(
88
88
  QuantumFunctionCall(
89
89
  function="allocate",
90
90
  positional_args=[
91
- Expression(expr="len(target)"),
91
+ Expression(expr="target.len"),
92
92
  HandleBinding(name="target"),
93
93
  ],
94
94
  ),
95
95
  QuantumFunctionCall(
96
96
  function="qaoa_penalty",
97
97
  params={
98
- "num_qubits": Expression(expr="len(target)"),
98
+ "num_qubits": Expression(expr="target.len"),
99
99
  "params_list": Expression(expr="params_list"),
100
100
  "hamiltonian": Expression(expr="hamiltonian"),
101
101
  },
@@ -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.39.0'
6
+ SEMVER_VERSION = '0.40.0'
7
7
  VERSION = str(Version(SEMVER_VERSION))
@@ -12,8 +12,8 @@ from classiq.interface.backend.quantum_backend_providers import (
12
12
  AliceBobBackendNames,
13
13
  AmazonBraketBackendNames,
14
14
  AzureQuantumBackendNames,
15
- ClassiqAerBackendNames,
16
15
  ClassiqNvidiaBackendNames,
16
+ ClassiqSimulatorBackendNames,
17
17
  IonqBackendNames,
18
18
  OQCBackendNames,
19
19
  ProviderTypeVendor,
@@ -56,7 +56,7 @@ class BackendPreferences(BaseModel):
56
56
  return False
57
57
 
58
58
 
59
- AWS_DEFAULT_JOB_TIMEOUT_SECONDS = int(timedelta(minutes=5).total_seconds())
59
+ AWS_DEFAULT_JOB_TIMEOUT_SECONDS = int(timedelta(minutes=240).total_seconds())
60
60
 
61
61
 
62
62
  class AliceBobBackendPreferences(BackendPreferences):
@@ -221,13 +221,13 @@ def is_exact_simulator(backend_preferences: BackendPreferences) -> bool:
221
221
 
222
222
 
223
223
  def default_backend_preferences(
224
- backend_name: str = ClassiqAerBackendNames.AER_SIMULATOR,
224
+ backend_name: str = ClassiqSimulatorBackendNames.SIMULATOR,
225
225
  ) -> BackendPreferences:
226
226
  return ClassiqBackendPreferences(backend_name=backend_name)
227
227
 
228
228
 
229
229
  def backend_preferences_field(
230
- backend_name: str = ClassiqAerBackendNames.AER_SIMULATOR,
230
+ backend_name: str = ClassiqSimulatorBackendNames.SIMULATOR,
231
231
  ) -> Any:
232
232
  return pydantic.Field(
233
233
  default_factory=lambda: default_backend_preferences(backend_name),
@@ -252,7 +252,7 @@ __all__ = [
252
252
  "AzureCredential",
253
253
  "AzureQuantumBackendNames",
254
254
  "ClassiqBackendPreferences",
255
- "ClassiqAerBackendNames",
255
+ "ClassiqSimulatorBackendNames",
256
256
  "IBMBackendPreferences",
257
257
  "IBMBackendProvider",
258
258
  "AwsBackendPreferences",
@@ -31,11 +31,11 @@ class ProviderTypeVendor:
31
31
  OQC = Literal[ProviderVendor.OQC]
32
32
 
33
33
 
34
- class ClassiqAerBackendNames(StrEnum):
35
- AER_SIMULATOR = "aer_simulator"
36
- AER_SIMULATOR_STATEVECTOR = "aer_simulator_statevector"
37
- AER_SIMULATOR_DENSITY_MATRIX = "aer_simulator_density_matrix"
38
- AER_SIMULATOR_MATRIX_PRODUCT_STATE = "aer_simulator_matrix_product_state"
34
+ class ClassiqSimulatorBackendNames(StrEnum):
35
+ SIMULATOR = "simulator"
36
+ SIMULATOR_STATEVECTOR = "simulator_statevector"
37
+ SIMULATOR_DENSITY_MATRIX = "simulator_density_matrix"
38
+ SIMULATOR_MATRIX_PRODUCT_STATE = "simulator_matrix_product_state"
39
39
 
40
40
 
41
41
  class IonqBackendNames(StrEnum):
@@ -141,7 +141,7 @@ class ClassiqNvidiaBackendNames(StrEnum):
141
141
  SIMULATOR = "nvidia_state_vector_simulator"
142
142
 
143
143
 
144
- AllClassiqBackendNames = Union[ClassiqAerBackendNames, ClassiqNvidiaBackendNames]
144
+ AllClassiqBackendNames = Union[ClassiqSimulatorBackendNames, ClassiqNvidiaBackendNames]
145
145
 
146
146
 
147
147
  class GoogleNvidiaBackendNames(StrEnum):
@@ -166,7 +166,7 @@ EXACT_SIMULATORS = {
166
166
  AmazonBraketBackendNames.AMAZON_BRAKET_SV1,
167
167
  AmazonBraketBackendNames.AMAZON_BRAKET_TN1,
168
168
  AmazonBraketBackendNames.AMAZON_BRAKET_DM1,
169
- *ClassiqAerBackendNames,
169
+ *ClassiqSimulatorBackendNames,
170
170
  *ClassiqNvidiaBackendNames,
171
171
  }
172
172
 
@@ -10,8 +10,9 @@ from classiq.interface.backend.backend_preferences import (
10
10
  backend_preferences_field,
11
11
  )
12
12
  from classiq.interface.backend.pydantic_backend import MAX_EXECUTION_TIMEOUT_SECONDS
13
- from classiq.interface.backend.quantum_backend_providers import ClassiqAerBackendNames
14
- from classiq.interface.executor.error_mitigation import ErrorMitigationMethod
13
+ from classiq.interface.backend.quantum_backend_providers import (
14
+ ClassiqSimulatorBackendNames,
15
+ )
15
16
  from classiq.interface.executor.optimizer_preferences import (
16
17
  OptimizerPreferences,
17
18
  OptimizerType,
@@ -51,11 +52,6 @@ class ExecutionPreferences(pydantic.BaseModel):
51
52
  default_factory=None,
52
53
  description="Settings related to VQE execution.",
53
54
  )
54
- error_mitigation_method: Optional[ErrorMitigationMethod] = pydantic.Field(
55
- default=None,
56
- description="Error mitigation method. Currently supports complete and tensored "
57
- "measurement calibration.",
58
- )
59
55
  noise_properties: Optional[NoiseProperties] = pydantic.Field(
60
56
  default=None, description="Properties of the noise in the circuit"
61
57
  )
@@ -64,7 +60,7 @@ class ExecutionPreferences(pydantic.BaseModel):
64
60
  description="The random seed used for the execution",
65
61
  )
66
62
  backend_preferences: BackendPreferencesTypes = backend_preferences_field(
67
- backend_name=ClassiqAerBackendNames.AER_SIMULATOR
63
+ backend_name=ClassiqSimulatorBackendNames.SIMULATOR
68
64
  )
69
65
  num_shots: Optional[pydantic.PositiveInt] = pydantic.Field(default=None)
70
66
  transpile_to_hardware: TranspilationOption = pydantic.Field(
@@ -151,7 +147,6 @@ def _choose_original_or_optimizer_attribute(
151
147
 
152
148
  __all__ = [
153
149
  "ExecutionPreferences",
154
- "ErrorMitigationMethod",
155
150
  "NoiseProperties",
156
151
  "OptimizerPreferences",
157
152
  "OptimizerType",
@@ -24,9 +24,7 @@ from classiq.interface.model.quantum_function_declaration import (
24
24
  )
25
25
 
26
26
  MOLECULE_PROBLEM_PARAM = {"molecule_problem": Struct(name="MoleculeProblem")}
27
- MOLECULE_PROBLEM_SIZE = (
28
- "len(get_field(molecule_problem_to_hamiltonian(molecule_problem)[0], 'pauli'))"
29
- )
27
+ MOLECULE_PROBLEM_SIZE = "get_field(get_field(molecule_problem_to_hamiltonian(molecule_problem)[0], 'pauli'), 'len')"
30
28
  MOLECULE_PROBLEM_PORT = {
31
29
  "qbv": PortDeclaration(
32
30
  name="qbv",
@@ -40,7 +38,7 @@ MOLECULE_PROBLEM_PORT = {
40
38
  FOCK_HAMILTONIAN_PROBLEM_PARAM = {
41
39
  "fock_hamiltonian_problem": Struct(name="FockHamiltonianProblem")
42
40
  }
43
- FOCK_HAMILTONIAN_SIZE = "len(get_field(fock_hamiltonian_problem_to_hamiltonian(fock_hamiltonian_problem)[0], 'pauli'))"
41
+ FOCK_HAMILTONIAN_SIZE = "get_field(get_field(fock_hamiltonian_problem_to_hamiltonian(fock_hamiltonian_problem)[0], 'pauli'), 'len')"
44
42
 
45
43
  FOCK_HAMILTONIAN_PROBLEM_PORT = {
46
44
  "qbv": PortDeclaration(
@@ -31,7 +31,7 @@ class FinanceModelType(Enum):
31
31
 
32
32
 
33
33
  FINANCE_FUNCTION_PORT_SIZE_MAPPING: Mapping[FinanceModelType, str] = {
34
- FinanceModelType.Gaussian: "get_field(finance_model, 'num_qubits') + len(get_field(finance_model, 'rhos')) + floor(log(sum(get_field(finance_model, 'loss')), 2)) + 1",
34
+ FinanceModelType.Gaussian: "get_field(finance_model, 'num_qubits') + get_field(get_field(finance_model, 'rhos'), 'len') + floor(log(sum(get_field(finance_model, 'loss')), 2)) + 1",
35
35
  FinanceModelType.LogNormal: "get_field(finance_model, 'num_qubits')",
36
36
  }
37
37
 
@@ -10,6 +10,7 @@ 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
13
14
 
14
15
  from classiq.exceptions import ClassiqArithmeticError, ClassiqValueError
15
16
 
@@ -174,6 +175,7 @@ class ExpressionValidator(ast.NodeVisitor):
174
175
  if not (
175
176
  isinstance(node.value, ast.Name)
176
177
  and node.value.id in self._supported_attr_values
178
+ or node.attr in CLASSICAL_ATTRIBUTES.keys()
177
179
  ):
178
180
  raise ClassiqValueError(
179
181
  f"Attribute is not supported for value {node.value}"
@@ -0,0 +1,82 @@
1
+ from typing import Optional, Tuple, Union
2
+
3
+ from classiq.interface.generator.expressions.expression import Expression
4
+ from classiq.interface.generator.expressions.qmod_sized_proxy import QmodSizedProxy
5
+ from classiq.interface.model.handle_binding import (
6
+ HandleBinding,
7
+ SlicedHandleBinding,
8
+ SubscriptHandleBinding,
9
+ )
10
+
11
+ from classiq.exceptions import ClassiqValueError
12
+
13
+ ILLEGAL_SLICING_STEP_MSG = "Slicing with a step of a quantum variable is not supported"
14
+ SLICE_OUT_OF_BOUNDS_MSG = "Slice end index out of bounds"
15
+ QARRAY_ELEMENT_NOT_SUBSCRIPTABLE = "Subscripting an element in QArray is illegal"
16
+
17
+
18
+ class QmodQArrayProxy(QmodSizedProxy):
19
+ def __init__(
20
+ self,
21
+ name: str,
22
+ size: int,
23
+ slice_: Optional[Tuple[int, int]] = None,
24
+ index_: Optional[int] = None,
25
+ ) -> None:
26
+ super().__init__(size)
27
+ self._name = name
28
+ self._slice = slice_
29
+ self._index = index_
30
+
31
+ def __getitem__(self, key: Union[slice, int]) -> "QmodQArrayProxy":
32
+ if self._index is not None:
33
+ raise ClassiqValueError(QARRAY_ELEMENT_NOT_SUBSCRIPTABLE)
34
+
35
+ new_index: Optional[int] = None
36
+
37
+ if isinstance(key, slice):
38
+ if key.step is not None:
39
+ raise ClassiqValueError(ILLEGAL_SLICING_STEP_MSG)
40
+ new_slice = self._get_new_slice(key.start, key.stop)
41
+ else:
42
+ new_slice = self._get_new_slice(key, key + 1)
43
+ new_index = new_slice[0]
44
+
45
+ if (self._slice is not None and new_slice[1] > self._slice[1]) or new_slice[
46
+ 1
47
+ ] > self._size:
48
+ raise ClassiqValueError(SLICE_OUT_OF_BOUNDS_MSG)
49
+
50
+ return QmodQArrayProxy(
51
+ self._name, self._size, slice_=new_slice, index_=new_index
52
+ )
53
+
54
+ def _get_new_slice(self, start: int, end: int) -> Tuple[int, int]:
55
+ if self._slice is not None:
56
+ return self._slice[0] + start, self._slice[0] + end
57
+ return start, end
58
+
59
+ @property
60
+ def index(self) -> Optional[int]:
61
+ return self._index
62
+
63
+ @property
64
+ def slice(self) -> Optional[Tuple[int, int]]:
65
+ return self._slice
66
+
67
+ @property
68
+ def handle(self) -> HandleBinding:
69
+ if self._index is not None:
70
+ return SubscriptHandleBinding(
71
+ name=self._name,
72
+ index=Expression(expr=str(self._index)),
73
+ )
74
+
75
+ if self._slice is not None:
76
+ return SlicedHandleBinding(
77
+ name=self._name,
78
+ start=Expression(expr=str(self._slice[0])),
79
+ end=Expression(expr=str(self._slice[1])),
80
+ )
81
+
82
+ return HandleBinding(name=self._name)
@@ -1,6 +1,9 @@
1
+ from typing import Any, Mapping
2
+
1
3
  from sympy import Symbol
2
4
 
3
5
  from classiq.interface.generator.expressions.qmod_sized_proxy import QmodSizedProxy
6
+ from classiq.interface.model.handle_binding import HandleBinding
4
7
 
5
8
 
6
9
  class QmodQScalarProxy(Symbol, QmodSizedProxy):
@@ -9,6 +12,11 @@ class QmodQScalarProxy(Symbol, QmodSizedProxy):
9
12
 
10
13
  def __init__(self, name: str, size: int) -> None:
11
14
  super().__init__(size)
15
+ self.name = name
16
+
17
+ @property
18
+ def handle(self) -> HandleBinding:
19
+ return HandleBinding(name=self.name)
12
20
 
13
21
 
14
22
  class QmodQBitProxy(QmodQScalarProxy):
@@ -24,6 +32,10 @@ class QmodQNumProxy(QmodQScalarProxy):
24
32
  self._fraction_digits = fraction_digits
25
33
  self._is_signed = is_signed
26
34
 
35
+ @property
36
+ def size(self) -> int:
37
+ return self._size
38
+
27
39
  @property
28
40
  def fraction_digits(self) -> int:
29
41
  return self._fraction_digits
@@ -31,3 +43,12 @@ class QmodQNumProxy(QmodQScalarProxy):
31
43
  @property
32
44
  def is_signed(self) -> bool:
33
45
  return self._is_signed
46
+
47
+ @property
48
+ def fields(self) -> Mapping[str, Any]:
49
+ return {
50
+ "size": self.size,
51
+ "is_signed": self.is_signed,
52
+ "fraction_digits": self.fraction_digits,
53
+ "len": self.size,
54
+ }
@@ -1,6 +1,28 @@
1
+ from typing import TYPE_CHECKING, Any, Mapping
2
+
3
+ from classiq.exceptions import ClassiqNotImplementedError
4
+
5
+ if TYPE_CHECKING:
6
+ from classiq.interface.model.handle_binding import HandleBinding
7
+
8
+
1
9
  class QmodSizedProxy:
2
10
  def __init__(self, size: int) -> None:
3
11
  self._size = size
4
12
 
5
13
  def __len__(self) -> int:
6
14
  return self._size
15
+
16
+ @property
17
+ def handle(self) -> "HandleBinding":
18
+ raise ClassiqNotImplementedError("cannot compute handle")
19
+
20
+ @property
21
+ def len(self) -> int:
22
+ return self._size
23
+
24
+ @property
25
+ def fields(self) -> Mapping[str, Any]:
26
+ return {
27
+ "len": self.len,
28
+ }
@@ -423,7 +423,7 @@ UNITARY_FUNCTION = QuantumFunctionDeclaration(
423
423
  DEFAULT_TARGET_NAME: PortDeclaration(
424
424
  name=DEFAULT_TARGET_NAME,
425
425
  direction=PortDeclarationDirection.Inout,
426
- size=Expression(expr="log(len(elements[0]), 2)"),
426
+ size=Expression(expr="log(get_field(elements[0], 'len'), 2)"),
427
427
  )
428
428
  },
429
429
  )
@@ -436,7 +436,7 @@ PREPARE_STATE_FUNCTION = QuantumFunctionDeclaration(
436
436
  "out": PortDeclaration(
437
437
  name="out",
438
438
  direction=PortDeclarationDirection.Output,
439
- size=Expression(expr="log(len(probabilities), 2)"),
439
+ size=Expression(expr="log(get_field(probabilities, 'len'), 2)"),
440
440
  )
441
441
  },
442
442
  )
@@ -448,7 +448,7 @@ PREPARE_AMPLITUDES_FUNCTION = QuantumFunctionDeclaration(
448
448
  "out": PortDeclaration(
449
449
  name="out",
450
450
  direction=PortDeclarationDirection.Output,
451
- size=Expression(expr="log(len(amplitudes), 2)"),
451
+ size=Expression(expr="log(get_field(amplitudes, 'len'), 2)"),
452
452
  )
453
453
  },
454
454
  )
@@ -467,7 +467,9 @@ ADD_FUNCTION = QuantumFunctionDeclaration(
467
467
  "result": PortDeclaration(
468
468
  name="result",
469
469
  direction=PortDeclarationDirection.Output,
470
- size=Expression(expr="Max(len(left), len(right)) + 1"),
470
+ size=Expression(
471
+ expr="Max(get_field(left, 'len'), get_field(right, 'len')) + 1"
472
+ ),
471
473
  ),
472
474
  },
473
475
  )
@@ -578,7 +580,7 @@ INPLACE_PREPARE_STATE = QuantumFunctionDeclaration(
578
580
  "target": PortDeclaration(
579
581
  name="target",
580
582
  direction=PortDeclarationDirection.Inout,
581
- size=Expression(expr="log(len(probabilities), 2)"),
583
+ size=Expression(expr="log(get_field(probabilities, 'len'), 2)"),
582
584
  )
583
585
  },
584
586
  )
@@ -591,7 +593,7 @@ INPLACE_PREPARE_AMPLITUDES = QuantumFunctionDeclaration(
591
593
  "target": PortDeclaration(
592
594
  name="target",
593
595
  direction=PortDeclarationDirection.Inout,
594
- size=Expression(expr="log(len(amplitudes), 2)"),
596
+ size=Expression(expr="log(get_field(amplitudes, 'len'), 2)"),
595
597
  )
596
598
  },
597
599
  )
@@ -26,7 +26,7 @@ SINGLE_PAULI_EXPONENT_FUNCTION = QuantumFunctionDeclaration(
26
26
  "qbv": PortDeclaration(
27
27
  name="qbv",
28
28
  direction=PortDeclarationDirection.Inout,
29
- size=Expression(expr="len(pauli_string)"),
29
+ size=Expression(expr="get_field(pauli_string, 'len')"),
30
30
  )
31
31
  },
32
32
  )
@@ -44,7 +44,9 @@ SUZUKI_TROTTER_FUNCTION = QuantumFunctionDeclaration(
44
44
  "qbv": PortDeclaration(
45
45
  name="qbv",
46
46
  direction=PortDeclarationDirection.Inout,
47
- size=Expression(expr="len(get_field(pauli_operator[0], 'pauli'))"),
47
+ size=Expression(
48
+ expr="get_field(get_field(pauli_operator[0], 'pauli'), 'len')"
49
+ ),
48
50
  )
49
51
  },
50
52
  )
@@ -60,7 +62,9 @@ QDRIFT_FUNCTION = QuantumFunctionDeclaration(
60
62
  "qbv": PortDeclaration(
61
63
  name="qbv",
62
64
  direction=PortDeclarationDirection.Inout,
63
- size=Expression(expr="len(get_field(pauli_operator[0], 'pauli'))"),
65
+ size=Expression(
66
+ expr="get_field(get_field(pauli_operator[0], 'pauli'), 'len')"
67
+ ),
64
68
  )
65
69
  },
66
70
  )
@@ -76,7 +80,9 @@ EXPONENTIATION_WITH_DEPTH_CONSTRAINT = QuantumFunctionDeclaration(
76
80
  "qbv": PortDeclaration(
77
81
  name="qbv",
78
82
  direction=PortDeclarationDirection.Inout,
79
- size=Expression(expr="len(get_field(pauli_operator[0], 'pauli'))"),
83
+ size=Expression(
84
+ expr="get_field(get_field(pauli_operator[0], 'pauli'), 'len')"
85
+ ),
80
86
  )
81
87
  },
82
88
  )