classiq 0.42.1__py3-none-any.whl → 0.43.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 (113) hide show
  1. classiq/__init__.py +2 -6
  2. classiq/_internals/api_wrapper.py +6 -12
  3. classiq/_internals/authentication/token_manager.py +5 -2
  4. classiq/_internals/jobs.py +5 -10
  5. classiq/analyzer/rb.py +3 -3
  6. classiq/applications/chemistry/chemistry_model_constructor.py +12 -8
  7. classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +2 -2
  8. classiq/applications/finance/finance_model_constructor.py +16 -13
  9. classiq/applications/qsvm/__init__.py +1 -3
  10. classiq/applications/qsvm/qsvm_model_constructor.py +7 -6
  11. classiq/exceptions.py +9 -4
  12. classiq/execution/execution_session.py +5 -2
  13. classiq/execution/qnn.py +1 -1
  14. classiq/executor.py +0 -2
  15. classiq/interface/_version.py +1 -1
  16. classiq/interface/chemistry/operator.py +19 -5
  17. classiq/interface/executor/constants.py +1 -0
  18. classiq/interface/finance/function_input.py +16 -10
  19. classiq/interface/generator/application_apis/chemistry_declarations.py +2 -2
  20. classiq/interface/generator/application_apis/qsvm_declarations.py +4 -2
  21. classiq/interface/generator/arith/argument_utils.py +20 -3
  22. classiq/interface/generator/arith/arithmetic_expression_validator.py +3 -26
  23. classiq/interface/generator/arith/binary_ops.py +8 -14
  24. classiq/interface/generator/arith/extremum_operations.py +30 -0
  25. classiq/interface/generator/arith/number_utils.py +1 -1
  26. classiq/interface/generator/arith/unary_ops.py +1 -3
  27. classiq/interface/generator/compiler_keywords.py +1 -1
  28. classiq/interface/generator/expressions/atomic_expression_functions.py +13 -3
  29. classiq/interface/generator/expressions/enums/__init__.py +0 -20
  30. classiq/interface/generator/expressions/enums/finance_functions.py +11 -18
  31. classiq/interface/generator/expressions/non_symbolic_expr.py +119 -0
  32. classiq/interface/generator/expressions/qmod_qarray_proxy.py +52 -37
  33. classiq/interface/generator/expressions/qmod_qscalar_proxy.py +16 -11
  34. classiq/interface/generator/expressions/qmod_sized_proxy.py +5 -5
  35. classiq/interface/generator/function_param_list_without_self_reference.py +0 -10
  36. classiq/interface/generator/function_params.py +0 -4
  37. classiq/interface/generator/functions/__init__.py +0 -20
  38. classiq/interface/generator/functions/builtins/core_library/exponentiation_functions.py +2 -2
  39. classiq/interface/generator/functions/builtins/open_lib_functions.py +530 -1
  40. classiq/interface/generator/functions/classical_type.py +22 -69
  41. classiq/interface/generator/functions/port_declaration.py +0 -11
  42. classiq/interface/generator/model/__init__.py +0 -1
  43. classiq/interface/generator/model/model.py +9 -185
  44. classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +3 -1
  45. classiq/interface/generator/types/builtin_enum_declarations.py +69 -0
  46. classiq/interface/generator/types/builtin_struct_declarations/pauli_struct_declarations.py +2 -2
  47. classiq/interface/generator/types/enum_declaration.py +57 -0
  48. classiq/interface/jobs.py +36 -65
  49. classiq/interface/model/bind_operation.py +3 -0
  50. classiq/interface/model/classical_parameter_declaration.py +3 -0
  51. classiq/interface/model/handle_binding.py +7 -0
  52. classiq/interface/model/inplace_binary_operation.py +13 -15
  53. classiq/interface/model/model.py +8 -20
  54. classiq/interface/model/native_function_definition.py +0 -17
  55. classiq/interface/model/quantum_function_call.py +63 -182
  56. classiq/interface/model/quantum_type.py +71 -10
  57. classiq/interface/server/routes.py +0 -6
  58. classiq/qmod/__init__.py +3 -3
  59. classiq/qmod/builtins/__init__.py +10 -1
  60. classiq/qmod/builtins/classical_execution_primitives.py +4 -2
  61. classiq/qmod/builtins/enums.py +177 -0
  62. classiq/qmod/builtins/functions.py +1 -2
  63. classiq/qmod/builtins/operations.py +2 -4
  64. classiq/qmod/builtins/structs.py +16 -17
  65. classiq/qmod/declaration_inferrer.py +23 -20
  66. classiq/qmod/model_state_container.py +2 -0
  67. classiq/qmod/native/pretty_printer.py +31 -13
  68. classiq/qmod/pretty_print/pretty_printer.py +52 -27
  69. classiq/qmod/qmod_constant.py +7 -3
  70. classiq/qmod/qmod_parameter.py +2 -1
  71. classiq/qmod/qmod_struct.py +9 -33
  72. classiq/qmod/qmod_variable.py +55 -22
  73. classiq/qmod/quantum_callable.py +6 -1
  74. classiq/qmod/quantum_expandable.py +29 -11
  75. classiq/qmod/quantum_function.py +8 -4
  76. classiq/qmod/semantics/annotation.py +38 -0
  77. classiq/qmod/semantics/error_manager.py +49 -0
  78. classiq/qmod/semantics/static_semantics_visitor.py +308 -0
  79. classiq/qmod/semantics/validation/func_call_validation.py +149 -0
  80. classiq/qmod/semantics/validation/types_validation.py +21 -0
  81. classiq/qmod/symbolic.py +6 -6
  82. classiq/qmod/symbolic_expr.py +26 -11
  83. classiq/qmod/utilities.py +23 -1
  84. {classiq-0.42.1.dist-info → classiq-0.43.0.dist-info}/METADATA +2 -2
  85. {classiq-0.42.1.dist-info → classiq-0.43.0.dist-info}/RECORD +88 -103
  86. classiq/_internals/_qfunc_ext.py +0 -6
  87. classiq/applications/libraries/ampltitude_estimation_library.py +0 -11
  88. classiq/interface/generator/credit_risk_example/linear_gci.py +0 -122
  89. classiq/interface/generator/credit_risk_example/weighted_adder.py +0 -69
  90. classiq/interface/generator/expressions/enums/chemistry.py +0 -28
  91. classiq/interface/generator/expressions/enums/classical_enum.py +0 -20
  92. classiq/interface/generator/expressions/enums/ladder_operator.py +0 -6
  93. classiq/interface/generator/expressions/enums/optimizers.py +0 -9
  94. classiq/interface/generator/expressions/enums/pauli.py +0 -8
  95. classiq/interface/generator/expressions/enums/qsvm_feature_map_entanglement.py +0 -9
  96. classiq/interface/generator/functions/foreign_function_definition.py +0 -114
  97. classiq/interface/generator/functions/function_implementation.py +0 -107
  98. classiq/interface/generator/functions/native_function_definition.py +0 -155
  99. classiq/interface/generator/functions/quantum_function_declaration.py +0 -69
  100. classiq/interface/generator/functions/register.py +0 -44
  101. classiq/interface/generator/functions/register_mapping_data.py +0 -106
  102. classiq/interface/generator/inequality_mixer.py +0 -51
  103. classiq/interface/generator/model/classical_main_validator.py +0 -106
  104. classiq/interface/generator/range_mixer.py +0 -56
  105. classiq/interface/generator/state_propagator.py +0 -74
  106. classiq/interface/model/resolvers/function_call_resolver.py +0 -64
  107. classiq/interface/model/validations/__init__.py +0 -0
  108. classiq/interface/model/validations/handle_validation_base.py +0 -55
  109. classiq/interface/model/validations/handles_validator.py +0 -153
  110. classiq/interface/model/validations/port_to_wire_name_generator.py +0 -12
  111. /classiq/{interface/generator/credit_risk_example → qmod/semantics}/__init__.py +0 -0
  112. /classiq/{interface/model/resolvers → qmod/semantics/validation}/__init__.py +0 -0
  113. {classiq-0.42.1.dist-info → classiq-0.43.0.dist-info}/WHEEL +0 -0
classiq/__init__.py CHANGED
@@ -9,17 +9,15 @@ from classiq.interface.generator.arith.register_user_input import (
9
9
  RegisterUserInput,
10
10
  )
11
11
  from classiq.interface.generator.control_state import ControlState
12
- from classiq.interface.generator.expressions.enums import * # noqa: F403
13
- from classiq.interface.generator.expressions.enums import __all__ as _enums_all
14
12
  from classiq.interface.generator.functions import * # noqa: F403
15
- from classiq.interface.generator.functions import __all__ as _ifunc_all
16
13
  from classiq.interface.generator.model import * # noqa: F403
17
14
  from classiq.interface.generator.model import __all__ as _md_all
18
15
  from classiq.interface.generator.quantum_program import QuantumProgram
16
+ from classiq.interface.generator.types.builtin_enum_declarations import * # noqa: F403
19
17
  from classiq.interface.ide.show import show
20
18
 
21
19
  from classiq import applications, exceptions, execution, synthesis
22
- from classiq._internals import _qfunc_ext, logger
20
+ from classiq._internals import logger
23
21
  from classiq._internals.async_utils import (
24
22
  enable_jupyter_notebook,
25
23
  is_notebook as _is_notebook,
@@ -99,11 +97,9 @@ __all__ = (
99
97
  "show",
100
98
  ]
101
99
  + _md_all
102
- + _ifunc_all
103
100
  + _sub_modules
104
101
  + _application_constructors_all
105
102
  + _qmod_all
106
- + _enums_all
107
103
  )
108
104
 
109
105
 
@@ -15,13 +15,7 @@ from classiq.interface.execution.jobs import (
15
15
  from classiq.interface.executor import execution_request
16
16
  from classiq.interface.generator import quantum_program as generator_result
17
17
  from classiq.interface.hardware import HardwareInformation
18
- from classiq.interface.jobs import (
19
- JobDescriptionBase,
20
- JobDescriptionFailure,
21
- JobDescriptionSuccess,
22
- JobID,
23
- JSONObject,
24
- )
18
+ from classiq.interface.jobs import JobDescription, JobID, JSONObject
25
19
  from classiq.interface.model.model import Model
26
20
  from classiq.interface.server import routes
27
21
 
@@ -49,13 +43,13 @@ class StatusType(Protocol):
49
43
 
50
44
 
51
45
  def _parse_job_response(
52
- job_result: JobDescriptionBase[JSONObject],
46
+ job_result: JobDescription[JSONObject],
53
47
  output_type: Type[ResultType],
54
48
  ) -> ResultType:
55
- if isinstance(job_result, JobDescriptionSuccess):
56
- return output_type.parse_obj(job_result.description)
57
- if isinstance(job_result, JobDescriptionFailure):
58
- raise ClassiqAPIError(job_result.description.details)
49
+ if job_result.result is not None:
50
+ return output_type.parse_obj(job_result.result)
51
+ if job_result.failure_details:
52
+ raise ClassiqAPIError(job_result.failure_details)
59
53
 
60
54
  raise ClassiqAPIError("Unexpected response from server")
61
55
 
@@ -2,7 +2,7 @@ import argparse
2
2
  import logging
3
3
  import threading
4
4
  import warnings
5
- from typing import Optional
5
+ from typing import Optional, Sequence, Type
6
6
 
7
7
  from classiq._internals.authentication import password_manager as pm
8
8
  from classiq._internals.authentication.auth0 import Auth0
@@ -13,7 +13,10 @@ from classiq.exceptions import (
13
13
  ClassiqPasswordManagerSelectionError,
14
14
  )
15
15
 
16
- PASSWORD_MANAGERS = [pm.KeyringPasswordManager, pm.FilePasswordManager]
16
+ PASSWORD_MANAGERS: Sequence[Type[pm.PasswordManager]] = [
17
+ pm.KeyringPasswordManager,
18
+ pm.FilePasswordManager,
19
+ ]
17
20
  _logger = logging.getLogger(__name__)
18
21
 
19
22
 
@@ -5,12 +5,7 @@ from typing import Callable, Dict, Iterable, Optional, Set, TypeVar
5
5
  import httpx
6
6
  import pydantic
7
7
 
8
- from classiq.interface.jobs import (
9
- JobDescriptionBase,
10
- JobDescriptionUnion,
11
- JobID,
12
- JSONObject,
13
- )
8
+ from classiq.interface.jobs import JobDescription, JobID, JSONObject
14
9
 
15
10
  from classiq._internals.async_utils import poll_for
16
11
  from classiq._internals.client import client, try_again_on_failure
@@ -18,7 +13,7 @@ from classiq._internals.config import SDKMode
18
13
  from classiq.exceptions import ClassiqAPIError
19
14
 
20
15
  _URL_PATH_SEP = "/"
21
- GeneralJobDescription = JobDescriptionBase[JSONObject]
16
+ GeneralJobDescription = JobDescription[JSONObject]
22
17
  _logger = logging.getLogger(__name__)
23
18
  T = TypeVar("T")
24
19
 
@@ -42,9 +37,9 @@ def _join_url_path(*parts: str) -> str:
42
37
  def _general_job_description_parser(
43
38
  json_response: JSONObject,
44
39
  ) -> Optional[GeneralJobDescription]:
45
- job_description = JobDescriptionUnion[JSONObject].parse_obj(json_response)
46
- if job_description.__root__.status.is_final():
47
- return job_description.__root__
40
+ job_description = GeneralJobDescription.parse_obj(json_response)
41
+ if job_description.status.is_final():
42
+ return job_description
48
43
  return None
49
44
 
50
45
 
classiq/analyzer/rb.py CHANGED
@@ -1,4 +1,4 @@
1
- from enum import Enum
1
+ from enum import Enum as PythonEnum
2
2
  from typing import Dict, List, Optional, Set, Union
3
3
 
4
4
  import matplotlib.pyplot as plt
@@ -78,8 +78,8 @@ class RBAnalysis:
78
78
  return fig
79
79
 
80
80
 
81
- def _strict_string(arg: Union[Enum, str]) -> str:
82
- if isinstance(arg, Enum):
81
+ def _strict_string(arg: Union[PythonEnum, str]) -> str:
82
+ if isinstance(arg, PythonEnum):
83
83
  return arg.value
84
84
  return arg
85
85
 
@@ -18,7 +18,7 @@ from classiq.interface.chemistry.ground_state_problem import (
18
18
  MoleculeProblem,
19
19
  )
20
20
  from classiq.interface.chemistry.molecule import Atom
21
- from classiq.interface.generator.expressions.enums.chemistry import (
21
+ from classiq.qmod.builtins.enums import (
22
22
  Element,
23
23
  FermionMapping,
24
24
  )
@@ -51,6 +51,7 @@ from classiq.applications.chemistry.chemistry_execution_parameters import (
51
51
  ChemistryExecutionParameters,
52
52
  )
53
53
  from classiq.exceptions import ClassiqError
54
+ from classiq.qmod.utilities import qmod_val_to_expr_str
54
55
 
55
56
  _LADDER_OPERATOR_TYPE_INDICATOR_TO_QMOD_MAPPING: Dict[str, str] = {
56
57
  "+": "PLUS",
@@ -153,7 +154,7 @@ _HAE_GATE_MAPPING: Dict[str, QuantumFunctionCall] = {
153
154
  ),
154
155
  "crx": QuantumFunctionCall(
155
156
  function="CRX",
156
- params={"theta": Expression(expr="angle")},
157
+ designated_params={"theta": Expression(expr="angle")},
157
158
  positional_args=[
158
159
  Expression(expr="angle"),
159
160
  HandleBinding(name="q1"),
@@ -194,7 +195,7 @@ _HAE_GATE_MAPPING: Dict[str, QuantumFunctionCall] = {
194
195
  def _atoms_to_qmod_atoms(atoms: List[Atom]) -> List[QmodChemistryAtom]:
195
196
  return [
196
197
  QmodChemistryAtom(
197
- element=Element[atom.symbol],
198
+ element=Element[atom.symbol], # type:ignore[arg-type]
198
199
  position=QmodPosition(
199
200
  x=atom.x, # type:ignore[arg-type]
200
201
  y=atom.y, # type:ignore[arg-type]
@@ -209,7 +210,9 @@ def molecule_problem_to_qmod(
209
210
  molecule_problem: MoleculeProblem,
210
211
  ) -> QmodMoleculeProblem:
211
212
  return QmodMoleculeProblem(
212
- mapping=FermionMapping[molecule_problem.mapping.value.upper()],
213
+ mapping=FermionMapping[ # type:ignore[arg-type]
214
+ molecule_problem.mapping.value.upper()
215
+ ],
213
216
  z2_symmetries=molecule_problem.z2_symmetries, # type:ignore[arg-type]
214
217
  molecule=QmodMolecule(
215
218
  atoms=_atoms_to_qmod_atoms(
@@ -256,11 +259,12 @@ def _summed_fermionic_operator_to_qmod_lader_terms(
256
259
  def _hamiltonian_problem_to_qmod_fock_hamiltonian_problem(
257
260
  hamiltonian_problem: HamiltonianProblem,
258
261
  ) -> str:
262
+ mapping = FermionMapping[hamiltonian_problem.mapping.value.upper()]
259
263
  return (
260
264
  # fmt: off
261
265
  "struct_literal("
262
266
  "FockHamiltonianProblem,"
263
- f"mapping={FermionMapping[hamiltonian_problem.mapping.value.upper()]},"
267
+ f"mapping={qmod_val_to_expr_str(mapping)},"
264
268
  f"z2_symmetries={hamiltonian_problem.z2_symmetries},"
265
269
  f"terms=[{_summed_fermionic_operator_to_qmod_lader_terms(hamiltonian_problem.hamiltonian)}],"
266
270
  f"num_particles={hamiltonian_problem.num_particles}"
@@ -271,7 +275,7 @@ def _hamiltonian_problem_to_qmod_fock_hamiltonian_problem(
271
275
 
272
276
  def _convert_library_problem_to_qmod_problem(problem: CHEMISTRY_PROBLEMS_TYPE) -> str:
273
277
  if isinstance(problem, MoleculeProblem):
274
- return str(molecule_problem_to_qmod(problem))
278
+ return qmod_val_to_expr_str(molecule_problem_to_qmod(problem))
275
279
  elif isinstance(problem, HamiltonianProblem):
276
280
  return _hamiltonian_problem_to_qmod_fock_hamiltonian_problem(problem)
277
281
  else:
@@ -368,13 +372,13 @@ def _get_molecule_problem_execution_post_processing(
368
372
  molecule_problem: MoleculeProblem,
369
373
  ) -> str:
370
374
  return f"""
371
- {_MOLECULE_PROBLEM_RESULT} = molecule_ground_state_solution_post_process({molecule_problem_to_qmod(molecule_problem)},{_EXECUTION_RESULT})
375
+ {_MOLECULE_PROBLEM_RESULT} = molecule_ground_state_solution_post_process({qmod_val_to_expr_str(molecule_problem_to_qmod(molecule_problem))},{_EXECUTION_RESULT})
372
376
  save({{{_MOLECULE_PROBLEM_RESULT!r}: {_MOLECULE_PROBLEM_RESULT}}})
373
377
  """
374
378
 
375
379
 
376
380
  def _is_parametric_gate(call: QuantumFunctionCall) -> bool:
377
- return len(call.params) > 0 or any(
381
+ return len(call.designated_params) > 0 or any(
378
382
  isinstance(arg, Expression) for arg in call.positional_args
379
383
  )
380
384
 
@@ -1,11 +1,11 @@
1
1
  from typing import List
2
2
 
3
- from classiq.interface.generator.expressions.enums.pauli import Pauli
4
3
  from classiq.interface.generator.functions.qmod_python_interface import QmodPyStruct
5
4
  from classiq.interface.helpers.custom_pydantic_types import PydanticPauliList
6
5
 
7
6
  from classiq.exceptions import ClassiqNonNumericCoefficientInPauliError
8
7
  from classiq.qmod.builtins import PauliTerm
8
+ from classiq.qmod.builtins.enums import Pauli
9
9
 
10
10
 
11
11
  def pauli_operator_to_hamiltonian(pauli_list: PydanticPauliList) -> List[PauliTerm]:
@@ -30,7 +30,7 @@ def pauli_enum_to_str(pauli: Pauli) -> str:
30
30
  Pauli.X: "Pauli.X",
31
31
  Pauli.Y: "Pauli.Y",
32
32
  Pauli.Z: "Pauli.Z",
33
- }.get(pauli, "")
33
+ }[pauli]
34
34
 
35
35
 
36
36
  def _pauli_terms_to_qmod(hamiltonian: List[PauliTerm]) -> str:
@@ -19,13 +19,11 @@ from classiq.interface.model.variable_declaration_statement import (
19
19
  VariableDeclarationStatement,
20
20
  )
21
21
 
22
- from classiq.applications.libraries.ampltitude_estimation_library import (
23
- AE_CLASSICAL_LIBRARY,
24
- )
25
22
  from classiq.applications.libraries.qmci_library import QMCI_LIBRARY
26
23
  from classiq.exceptions import ClassiqError
24
+ from classiq.qmod.utilities import qmod_val_to_expr_str
27
25
 
28
- _OUTPUT_VARIABLE_NAME = "result"
26
+ _OUTPUT_VARIABLE_NAME = "payoff_estimation"
29
27
 
30
28
 
31
29
  def construct_finance_model(
@@ -59,7 +57,7 @@ def construct_finance_model(
59
57
  if finance_function_input.tail_probability is not None:
60
58
  tail_probability = finance_function_input.tail_probability
61
59
 
62
- finance_function_object = f"struct_literal(FinanceFunction, f={finance_function_input.f}, threshold={finance_function_input.condition.threshold}, larger={finance_function_input.condition.larger}, polynomial_degree={polynomial_degree}, use_chebyshev_polynomial_approximation={finance_function_input.use_chebyshev_polynomial_approximation}, tail_probability={tail_probability})"
60
+ finance_function_object = f"struct_literal(FinanceFunction, f={qmod_val_to_expr_str(finance_function_input.f)}, threshold={finance_function_input.condition.threshold}, larger={finance_function_input.condition.larger}, polynomial_degree={polynomial_degree}, use_chebyshev_polynomial_approximation={finance_function_input.use_chebyshev_polynomial_approximation}, tail_probability={tail_probability})"
63
61
  num_unitary_qubits = total_num_qubits + 1
64
62
 
65
63
  model = Model(
@@ -117,13 +115,18 @@ def construct_finance_model(
117
115
  ],
118
116
  ),
119
117
  ],
120
- classical_execution_code=(
121
- AE_CLASSICAL_LIBRARY
122
- + f"""
123
- estimation = execute_amplitude_estimation({phase_port_size})
124
- {_OUTPUT_VARIABLE_NAME} = {post_process_function}({finance_model}, {finance_function_object}, estimation)
125
- save({{{_OUTPUT_VARIABLE_NAME!r}: {_OUTPUT_VARIABLE_NAME}}})
126
- """
127
- ).strip(),
118
+ classical_execution_code=f"""
119
+ phase_port_size = {phase_port_size}
120
+ counts = sample()
121
+ save({{"counts": counts}})
122
+ probability_estimation = qae_with_qpe_result_post_processing(
123
+ estimation_register_size=phase_port_size,
124
+ estimation_method=1,
125
+ result=counts
126
+ )
127
+ save({{"probability_estimation": probability_estimation}})
128
+ {_OUTPUT_VARIABLE_NAME} = {post_process_function}({finance_model}, {finance_function_object}, probability_estimation)
129
+ save({{"{_OUTPUT_VARIABLE_NAME}": {_OUTPUT_VARIABLE_NAME}}})
130
+ """.strip(),
128
131
  )
129
132
  return model.get_model()
@@ -1,6 +1,4 @@
1
- from classiq.interface.generator.expressions.enums.qsvm_feature_map_entanglement import (
2
- QSVMFeatureMapEntanglement,
3
- )
1
+ from classiq.qmod.builtins.enums import QSVMFeatureMapEntanglement
4
2
 
5
3
  from ..qsvm import qsvm_data_generation
6
4
  from .qsvm import * # noqa: F403
@@ -1,10 +1,6 @@
1
1
  from typing import Any, List, Tuple
2
2
 
3
3
  from classiq.interface.applications.qsvm import DataList, LabelsInt
4
- from classiq.interface.generator.expressions.enums.pauli import Pauli
5
- from classiq.interface.generator.expressions.enums.qsvm_feature_map_entanglement import (
6
- QSVMFeatureMapEntanglement,
7
- )
8
4
  from classiq.interface.generator.expressions.expression import Expression
9
5
  from classiq.interface.generator.functions.port_declaration import (
10
6
  PortDeclarationDirection,
@@ -16,6 +12,8 @@ from classiq.interface.model.port_declaration import PortDeclaration
16
12
  from classiq.interface.model.quantum_function_call import QuantumFunctionCall
17
13
 
18
14
  from classiq.exceptions import ClassiqValueError
15
+ from classiq.qmod.builtins.enums import Pauli, QSVMFeatureMapEntanglement
16
+ from classiq.qmod.utilities import qmod_val_to_expr_str
19
17
 
20
18
  INVALID_FEATURE_MAP_FUNC_NAME_MSG = "Invalid feature_map_function_name, it can be bloch_sphere_feature_map or pauli_feature_map"
21
19
 
@@ -40,13 +38,16 @@ def _pauli_feature_map_function_params(
40
38
  paulis_str = (
41
39
  "["
42
40
  + ",".join(
43
- ["[" + ",".join([str(p) for p in p_list]) + "]" for p_list in paulis]
41
+ [
42
+ "[" + ",".join([qmod_val_to_expr_str(p) for p in p_list]) + "]"
43
+ for p_list in paulis
44
+ ]
44
45
  )
45
46
  + "]"
46
47
  )
47
48
  pauli_feature_map_params = (
48
49
  f"paulis={paulis_str}, "
49
- f"entanglement={entanglement}, "
50
+ f"entanglement={qmod_val_to_expr_str(entanglement)}, "
50
51
  f"alpha={alpha}, "
51
52
  f"reps={reps}, "
52
53
  f"feature_dimension={feature_dimension}"
classiq/exceptions.py CHANGED
@@ -4,16 +4,17 @@ from typing import Iterable, List
4
4
  _logger = logging.getLogger(__name__)
5
5
 
6
6
  CLASSIQ_SLACK_COMMUNITY_LINK = (
7
- "\nIf you need further assistance, please reach out on our Community Slack channel at: https://short.classiq.io/join-slack"
8
- "\nIf the error persists feel free to open a ticket at: https://short.classiq.io/support"
7
+ "\nIf you need further assistance, please reach out on our Community Slack channel "
8
+ "at: https://short.classiq.io/join-slack"
9
9
  )
10
10
 
11
11
 
12
12
  class ClassiqError(Exception):
13
13
  def __init__(self, message: str) -> None:
14
- message_with_link = message + CLASSIQ_SLACK_COMMUNITY_LINK
15
- super().__init__(message_with_link)
16
14
  self._raw_message = message
15
+ if CLASSIQ_SLACK_COMMUNITY_LINK not in message:
16
+ message = message + CLASSIQ_SLACK_COMMUNITY_LINK
17
+ super().__init__(message)
17
18
 
18
19
  @property
19
20
  def raw_message(self) -> str:
@@ -171,3 +172,7 @@ class ClassiqExecutorInvalidHamiltonianError(ClassiqCombOptError):
171
172
 
172
173
  def __init__(self) -> None:
173
174
  super().__init__("Invalid hamiltonian")
175
+
176
+
177
+ class ClassiqSemanticError(ClassiqError):
178
+ pass
@@ -19,7 +19,10 @@ from classiq.applications.combinatorial_helpers.pauli_helpers.pauli_utils import
19
19
  from classiq.exceptions import ClassiqValueError
20
20
  from classiq.executor import execute
21
21
  from classiq.qmod.builtins import PauliTerm
22
- from classiq.qmod.builtins.classical_execution_primitives import ExecutionParams
22
+ from classiq.qmod.builtins.classical_execution_primitives import (
23
+ CARRAY_SEPARATOR,
24
+ ExecutionParams,
25
+ )
23
26
  from classiq.synthesis import SerializedQuantumProgram
24
27
 
25
28
  Hamiltonian = Union[List[QmodPyStruct], List[PauliTerm]]
@@ -70,7 +73,7 @@ def parse_params(params: ExecutionParams) -> ParsedExecutionParams:
70
73
  for key, values in params.items():
71
74
  if isinstance(values, list):
72
75
  for index, value in enumerate(values):
73
- new_key = f"{key}_{index}"
76
+ new_key = f"{key}{CARRAY_SEPARATOR}{index}"
74
77
  result[new_key] = value
75
78
  elif isinstance(values, (int, float)):
76
79
  result[key] = values
classiq/execution/qnn.py CHANGED
@@ -4,6 +4,7 @@ from typing import List, Optional
4
4
  import more_itertools
5
5
 
6
6
  from classiq.interface.chemistry.operator import PauliOperator
7
+ from classiq.interface.executor.constants import DEFAULT_RESULT_NAME
7
8
  from classiq.interface.executor.execution_result import (
8
9
  ResultsCollection,
9
10
  SavedResultValueType,
@@ -16,7 +17,6 @@ from classiq.applications.combinatorial_helpers.pauli_helpers.pauli_utils import
16
17
  pauli_operator_to_hamiltonian,
17
18
  )
18
19
  from classiq.execution.execution_session import ExecutionSession
19
- from classiq.executor import DEFAULT_RESULT_NAME
20
20
  from classiq.synthesis import SerializedQuantumProgram
21
21
 
22
22
  _MAX_ARGUMENTS_SIZE = 1024
classiq/executor.py CHANGED
@@ -17,8 +17,6 @@ from classiq._internals.async_utils import syncify_function
17
17
  from classiq.execution.jobs import ExecutionJob
18
18
  from classiq.synthesis import SerializedQuantumProgram
19
19
 
20
- DEFAULT_RESULT_NAME = "result"
21
-
22
20
  BatchExecutionResult: TypeAlias = Union[ExecutionDetails, BaseException]
23
21
  ProgramAndResult: TypeAlias = Tuple[QuantumCode, BatchExecutionResult]
24
22
  BackendPreferencesAndResult: TypeAlias = Tuple[
@@ -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.42.1'
6
+ SEMVER_VERSION = '0.43.0'
7
7
  VERSION = str(Version(SEMVER_VERSION))
@@ -1,12 +1,21 @@
1
1
  from functools import reduce
2
- from typing import Any, Collection, Dict, List, Optional, Tuple, Union, cast
2
+ from typing import (
3
+ TYPE_CHECKING,
4
+ Any,
5
+ Collection,
6
+ Dict,
7
+ List,
8
+ Optional,
9
+ Tuple,
10
+ Union,
11
+ cast,
12
+ )
3
13
 
4
14
  import numpy as np
5
15
  import pydantic
6
16
  import sympy
7
17
  from more_itertools import all_equal
8
18
 
9
- from classiq.interface.generator.expressions.enums.pauli import Pauli
10
19
  from classiq.interface.generator.function_params import validate_expression_str
11
20
  from classiq.interface.generator.parameters import (
12
21
  ParameterComplexType,
@@ -25,6 +34,9 @@ from classiq.interface.helpers.versioned_model import VersionedModel
25
34
 
26
35
  from classiq.exceptions import ClassiqValueError
27
36
 
37
+ if TYPE_CHECKING:
38
+ from classiq.qmod.builtins.enums import Pauli
39
+
28
40
 
29
41
  class PauliOperator(HashablePydanticBaseModel, VersionedModel):
30
42
  """
@@ -204,7 +216,7 @@ class PauliOperator(HashablePydanticBaseModel, VersionedModel):
204
216
  @classmethod
205
217
  def from_unzipped_lists(
206
218
  cls,
207
- operators: List[List[Pauli]],
219
+ operators: List[List["Pauli"]],
208
220
  coefficients: Optional[List[complex]] = None,
209
221
  ) -> "PauliOperator":
210
222
  if coefficients is None:
@@ -404,7 +416,7 @@ class PauliOperatorV1(HashablePydanticBaseModel):
404
416
  @classmethod
405
417
  def from_unzipped_lists(
406
418
  cls,
407
- operators: List[List[Pauli]],
419
+ operators: List[List["Pauli"]],
408
420
  coefficients: Optional[List[complex]] = None,
409
421
  ) -> "PauliOperatorV1":
410
422
  if coefficients is None:
@@ -466,7 +478,9 @@ def validate_operator_has_no_complex_coefficients(
466
478
  return pauli_operator
467
479
 
468
480
 
469
- def pauli_integers_to_str(paulis: List[Pauli]) -> str:
481
+ def pauli_integers_to_str(paulis: List["Pauli"]) -> str:
482
+ from classiq.qmod.builtins.enums import Pauli
483
+
470
484
  return "".join([Pauli(pauli).name for pauli in paulis])
471
485
 
472
486
 
@@ -0,0 +1 @@
1
+ DEFAULT_RESULT_NAME = "result"
@@ -1,10 +1,9 @@
1
- from typing import Any, Dict, Optional, Union
1
+ from typing import TYPE_CHECKING, Any, Dict, Optional, Union
2
2
 
3
3
  import pydantic
4
4
 
5
5
  from classiq.interface.generator.expressions.enums.finance_functions import (
6
- FINANCE_FUNCTION_STRING,
7
- FinanceFunctionType,
6
+ get_finance_function_dict,
8
7
  )
9
8
  from classiq.interface.helpers.custom_pydantic_types import (
10
9
  PydanticNonZeroProbabilityFloat,
@@ -12,6 +11,9 @@ from classiq.interface.helpers.custom_pydantic_types import (
12
11
 
13
12
  from classiq.exceptions import ClassiqValueError
14
13
 
14
+ if TYPE_CHECKING:
15
+ from classiq.qmod.builtins.enums import FinanceFunctionType
16
+
15
17
 
16
18
  class FunctionCondition(pydantic.BaseModel):
17
19
  threshold: float
@@ -25,7 +27,7 @@ class FunctionCondition(pydantic.BaseModel):
25
27
 
26
28
 
27
29
  class FinanceFunctionInput(pydantic.BaseModel):
28
- f: FinanceFunctionType = pydantic.Field(
30
+ f: "FinanceFunctionType" = pydantic.Field(
29
31
  description="An enumeration of the wanted financial function: VaR, expected "
30
32
  "shortfall, European call options or x^2"
31
33
  )
@@ -50,10 +52,10 @@ class FinanceFunctionInput(pydantic.BaseModel):
50
52
  )
51
53
 
52
54
  @pydantic.validator("f", pre=True)
53
- def _convert_f_if_str(cls, f: Any) -> FinanceFunctionType:
55
+ def _convert_f_if_str(cls, f: Any) -> "FinanceFunctionType":
54
56
  # Keep this for backwards-compatible string support
55
- if f in FINANCE_FUNCTION_STRING:
56
- return FINANCE_FUNCTION_STRING[f]
57
+ if f in get_finance_function_dict():
58
+ return get_finance_function_dict()[f]
57
59
  return f
58
60
 
59
61
  @pydantic.validator("use_chebyshev_polynomial_approximation")
@@ -68,13 +70,15 @@ class FinanceFunctionInput(pydantic.BaseModel):
68
70
 
69
71
  @pydantic.validator("f")
70
72
  def _validate_finance_function(
71
- cls, f: Union[int, str, FinanceFunctionType]
72
- ) -> FinanceFunctionType:
73
+ cls, f: Union[int, str, "FinanceFunctionType"]
74
+ ) -> "FinanceFunctionType":
75
+ from classiq.qmod.builtins.enums import FinanceFunctionType
76
+
73
77
  if isinstance(f, FinanceFunctionType):
74
78
  return f
75
79
  if isinstance(f, int):
76
80
  return FinanceFunctionType(f)
77
- return FinanceFunctionType.from_string(f)
81
+ return get_finance_function_dict()[f]
78
82
 
79
83
  @pydantic.validator("tail_probability", always=True)
80
84
  def _validate_tail_probability_assignment_for_shortfall(
@@ -82,6 +86,8 @@ class FinanceFunctionInput(pydantic.BaseModel):
82
86
  tail_probability: Optional[PydanticNonZeroProbabilityFloat],
83
87
  values: Dict[str, Any],
84
88
  ) -> Optional[PydanticNonZeroProbabilityFloat]:
89
+ from classiq.qmod.builtins.enums import FinanceFunctionType
90
+
85
91
  if values.get("f") == FinanceFunctionType.SHORTFALL and not tail_probability:
86
92
  raise ClassiqValueError(
87
93
  "Tail probability must be set for expected shortfall"
@@ -9,9 +9,9 @@ from classiq.interface.generator.functions.classical_type import (
9
9
  Bool,
10
10
  ClassicalList,
11
11
  Integer,
12
- LadderOperator,
13
12
  Real,
14
13
  Struct,
14
+ TypeName,
15
15
  VQEResult,
16
16
  )
17
17
  from classiq.interface.generator.functions.port_declaration import (
@@ -169,7 +169,7 @@ LADDER_TERM = StructDeclaration(
169
169
  LADDER_OP = StructDeclaration(
170
170
  name="LadderOp",
171
171
  variables={
172
- "op": LadderOperator(),
172
+ "op": TypeName(name="LadderOperator"),
173
173
  "index": Integer(),
174
174
  },
175
175
  )
@@ -3,8 +3,8 @@ import enum
3
3
  from classiq.interface.generator.expressions.expression import Expression
4
4
  from classiq.interface.generator.functions.classical_type import (
5
5
  ClassicalList,
6
+ Enum,
6
7
  Integer,
7
- Pauli,
8
8
  Real,
9
9
  Struct,
10
10
  )
@@ -56,7 +56,9 @@ QSVM_FEATURE_MAP_PAULI = StructDeclaration(
56
56
  "reps": Integer(),
57
57
  "entanglement": Integer(),
58
58
  "alpha": Real(),
59
- "paulis": ClassicalList(element_type=ClassicalList(element_type=Pauli())),
59
+ "paulis": ClassicalList(
60
+ element_type=ClassicalList(element_type=Enum(name="Pauli"))
61
+ ),
60
62
  },
61
63
  )
62
64
 
@@ -49,10 +49,27 @@ def bounds(argument: RegisterOrConst) -> Tuple[float, float]:
49
49
 
50
50
 
51
51
  def limit_fraction_places(
52
- argument: RegisterOrConst, *, machine_precision: int
52
+ argument: RegisterOrConst, machine_precision: int
53
53
  ) -> RegisterOrConst:
54
54
  if isinstance(argument, RegisterArithmeticInfo):
55
55
  return argument.limit_fraction_places(machine_precision)
56
- return number_utils.limit_fraction_places(
57
- argument, machine_precision=machine_precision
56
+ return number_utils.limit_fraction_places(argument, machine_precision)
57
+
58
+
59
+ def arg_bounds_overlap(args: Tuple[RegisterOrConst, RegisterOrConst]) -> bool:
60
+ return (max(bounds(args[0])) - min(bounds(args[1]))) * (
61
+ min(bounds(args[0])) - max(bounds(args[1]))
62
+ ) < 0
63
+
64
+
65
+ def as_arithmetic_info(
66
+ arg: RegisterOrConst, with_bounds: bool = True
67
+ ) -> RegisterArithmeticInfo:
68
+ if isinstance(arg, RegisterArithmeticInfo):
69
+ return arg
70
+ return RegisterArithmeticInfo(
71
+ size=number_utils.size(arg),
72
+ is_signed=arg < 0,
73
+ fraction_places=number_utils.fraction_places(arg),
74
+ bounds=(arg, arg) if with_bounds else None,
58
75
  )