classiq 0.89.0__py3-none-any.whl → 0.90.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.

Potentially problematic release.


This version of classiq might be problematic. Click here for more details.

Files changed (86) hide show
  1. classiq/__init__.py +1 -0
  2. classiq/_internals/api_wrapper.py +16 -32
  3. classiq/analyzer/show_interactive_hack.py +26 -1
  4. classiq/applications/chemistry/chemistry_model_constructor.py +14 -2
  5. classiq/applications/combinatorial_helpers/pyomo_utils.py +9 -6
  6. classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +2 -2
  7. classiq/applications/combinatorial_optimization/combinatorial_problem.py +16 -8
  8. classiq/evaluators/classical_expression.py +63 -41
  9. classiq/evaluators/control.py +31 -52
  10. classiq/evaluators/expression_evaluator.py +8 -4
  11. classiq/evaluators/parameter_types.py +200 -104
  12. classiq/evaluators/qmod_annotated_expression.py +3 -1
  13. classiq/evaluators/qmod_node_evaluators/classical_function_evaluation.py +12 -37
  14. classiq/evaluators/qmod_node_evaluators/constant_evaluation.py +8 -17
  15. classiq/evaluators/qmod_node_evaluators/measurement_evaluation.py +1 -1
  16. classiq/evaluators/qmod_node_evaluators/min_max_evaluation.py +7 -1
  17. classiq/evaluators/qmod_node_evaluators/name_evaluation.py +0 -1
  18. classiq/evaluators/qmod_node_evaluators/numeric_attrs_utils.py +9 -1
  19. classiq/evaluators/qmod_node_evaluators/utils.py +33 -0
  20. classiq/evaluators/qmod_type_inference/classical_type_inference.py +4 -7
  21. classiq/interface/_version.py +1 -1
  22. classiq/interface/analyzer/analysis_params.py +1 -25
  23. classiq/interface/analyzer/result.py +4 -0
  24. classiq/interface/chemistry/ground_state_problem.py +16 -2
  25. classiq/interface/executor/optimizer_preferences.py +0 -112
  26. classiq/interface/generator/application_apis/chemistry_declarations.py +3 -1
  27. classiq/interface/generator/arith/arithmetic_expression_validator.py +2 -7
  28. classiq/interface/generator/expressions/evaluated_expression.py +3 -13
  29. classiq/interface/generator/expressions/expression_types.py +8 -22
  30. classiq/interface/generator/expressions/proxies/classical/classical_proxy.py +2 -2
  31. classiq/interface/generator/expressions/proxies/classical/classical_struct_proxy.py +1 -2
  32. classiq/interface/generator/functions/concrete_types.py +1 -1
  33. classiq/interface/generator/generated_circuit_data.py +4 -0
  34. classiq/interface/generator/preferences/qasm_to_qmod_params.py +14 -0
  35. classiq/interface/helpers/model_normalizer.py +0 -6
  36. classiq/interface/ide/visual_model.py +1 -0
  37. classiq/interface/model/handle_binding.py +1 -1
  38. classiq/interface/model/port_declaration.py +2 -1
  39. classiq/interface/model/quantum_expressions/arithmetic_operation.py +16 -12
  40. classiq/interface/model/quantum_type.py +1 -1
  41. classiq/interface/server/routes.py +2 -3
  42. classiq/model_expansions/atomic_expression_functions_defs.py +4 -22
  43. classiq/model_expansions/capturing/captured_vars.py +7 -3
  44. classiq/model_expansions/closure.py +8 -0
  45. classiq/model_expansions/interpreters/base_interpreter.py +84 -22
  46. classiq/model_expansions/interpreters/frontend_generative_interpreter.py +1 -1
  47. classiq/model_expansions/interpreters/generative_interpreter.py +7 -5
  48. classiq/model_expansions/quantum_operations/allocate.py +92 -21
  49. classiq/model_expansions/quantum_operations/assignment_result_processor.py +28 -27
  50. classiq/model_expansions/quantum_operations/call_emitter.py +32 -26
  51. classiq/model_expansions/quantum_operations/classical_var_emitter.py +6 -2
  52. classiq/model_expansions/quantum_operations/emitter.py +39 -69
  53. classiq/model_expansions/quantum_operations/expression_evaluator.py +13 -2
  54. classiq/model_expansions/quantum_operations/quantum_function_call.py +4 -5
  55. classiq/model_expansions/quantum_operations/variable_decleration.py +16 -11
  56. classiq/model_expansions/scope.py +36 -29
  57. classiq/model_expansions/scope_initialization.py +3 -6
  58. classiq/model_expansions/sympy_conversion/sympy_to_python.py +6 -2
  59. classiq/model_expansions/transformers/model_renamer.py +35 -64
  60. classiq/model_expansions/transformers/type_modifier_inference.py +6 -6
  61. classiq/model_expansions/visitors/boolean_expression_transformers.py +7 -31
  62. classiq/model_expansions/visitors/symbolic_param_inference.py +9 -3
  63. classiq/open_library/functions/state_preparation.py +3 -3
  64. classiq/qmod/builtins/functions/allocation.py +8 -8
  65. classiq/qmod/builtins/functions/arithmetic.py +1 -1
  66. classiq/qmod/builtins/functions/chemistry.py +64 -0
  67. classiq/qmod/builtins/functions/exponentiation.py +7 -13
  68. classiq/qmod/builtins/functions/qsvm.py +1 -1
  69. classiq/qmod/builtins/operations.py +38 -10
  70. classiq/qmod/generative.py +2 -4
  71. classiq/qmod/native/pretty_printer.py +1 -1
  72. classiq/qmod/pretty_print/pretty_printer.py +1 -1
  73. classiq/qmod/qmod_constant.py +1 -1
  74. classiq/qmod/qmod_parameter.py +2 -2
  75. classiq/qmod/qmod_variable.py +15 -15
  76. classiq/qmod/quantum_expandable.py +1 -1
  77. classiq/synthesis.py +37 -1
  78. classiq/visualization.py +1 -1
  79. {classiq-0.89.0.dist-info → classiq-0.90.0.dist-info}/METADATA +1 -1
  80. {classiq-0.89.0.dist-info → classiq-0.90.0.dist-info}/RECORD +81 -85
  81. classiq/evaluators/arg_type_match.py +0 -168
  82. classiq/evaluators/classical_type_inference.py +0 -121
  83. classiq/interface/combinatorial_optimization/optimization_problem.py +0 -17
  84. classiq/interface/combinatorial_optimization/result.py +0 -9
  85. classiq/model_expansions/transformers/ast_renamer.py +0 -26
  86. {classiq-0.89.0.dist-info → classiq-0.90.0.dist-info}/WHEEL +0 -0
@@ -1,5 +1,6 @@
1
1
  import inspect
2
2
  import sys
3
+ import warnings
3
4
  from collections.abc import Mapping
4
5
  from types import FrameType
5
6
  from typing import (
@@ -12,7 +13,7 @@ from typing import (
12
13
  overload,
13
14
  )
14
15
 
15
- from classiq.interface.exceptions import ClassiqValueError
16
+ from classiq.interface.exceptions import ClassiqDeprecationWarning, ClassiqValueError
16
17
  from classiq.interface.generator.expressions.expression import Expression
17
18
  from classiq.interface.generator.functions.builtins.internal_operators import (
18
19
  REPEAT_OPERATOR_NAME,
@@ -516,27 +517,54 @@ def invert(stmt_block: Union[QCallable, Callable[[], Statements]]) -> None:
516
517
  QCallable.CURRENT_EXPANDABLE.append_statement_to_body(invert_stmt)
517
518
 
518
519
 
520
+ @overload
521
+ def phase(phase_expr: Union[SymbolicExpr, float], theta: float = 1.0) -> None:
522
+ pass
523
+
524
+
525
+ @overload
526
+ def phase(*, expr: Union[SymbolicExpr, float], theta: float = 1.0) -> None:
527
+ pass
528
+
529
+
519
530
  @suppress_return_value
520
- def phase(expr: SymbolicExpr, theta: float = 1.0) -> None:
531
+ def phase(
532
+ phase_expr: Union[SymbolicExpr, float, None] = None,
533
+ theta: float = 1.0,
534
+ expr: Any = None,
535
+ ) -> None:
521
536
  """
522
- Applies a state-dependent phase shift to the quantum state.
537
+ Applies a state-dependent or fixed phase shift (Z rotation) to the quantum state.
523
538
 
524
- This operation multiplies each basis state |x> by a complex phase factor `theta * expr(x)`,
525
- where `expr` is a symbolic expression dependent on the state value `x`, and `theta` is a scalar multiplier.
539
+ This operation multiplies each computational-basis state $|x_1,x_2,\\ldots,x_n\\rangle$
540
+ by a complex phase factor $\\theta * \\text{phase_expr}(x_1,x_2,\\ldots,x_n)$, where
541
+ `phase_expr` is a symbolic expression that contains quantum variables $x_1,x_2,\\ldots,x_n$,
542
+ and `theta` is a scalar multiplier. If `phase_expr` contains no quantum variables,
543
+ all states are rotated by the same fixed angle.
526
544
 
527
545
  Args:
528
- expr: A symbolic expression that evaluates to an angle (in radians) as a function of the quantum state value `x`.
529
- theta: (Optional) A scalar multiplier for the evaluated expression. Defaults to 1.0.
546
+ phase_expr: A symbolic expression that evaluates to an angle (in radians) as a function of the state of the quantum variables occurring in it, if any, or otherwise a fixed value. Execution parameters are only allowed if no quantum variables occur in the expression.
547
+ theta: (Optional, allowed only together with quantum expressions) A scalar multiplier for the evaluated expression, optionally containing execution parameters. Defaults to 1.0.
530
548
 
531
549
  Note:
532
- The `phase` operation is equivalent to a Z-rotation up to a global phase. It is commonly used
533
- to apply relative phase shifts conditioned on the quantum state.
550
+ The `phase` statement is a generalization of the `PHASE()` atomic function, and
551
+ they are equivalent when the phase_expr is a single-qubit variable.
534
552
  """
535
553
  assert QCallable.CURRENT_EXPANDABLE is not None
554
+ if expr is not None:
555
+ warnings.warn(
556
+ "Parameter 'expr' of function 'phase' has been renamed to "
557
+ "'phase_expr'. Parameter 'expr' will no longer be supported starting on "
558
+ "2025-09-19 at the earliest.\nHint: Change `phase(expr=..., theta=...)` to "
559
+ "`phase(phase_expr=..., theta=...)` or `phase(..., ...)`.",
560
+ category=ClassiqDeprecationWarning,
561
+ stacklevel=2,
562
+ )
563
+ phase_expr = expr
536
564
  source_ref = get_source_ref(sys._getframe(1))
537
565
  QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
538
566
  PhaseOperation(
539
- expression=Expression(expr=str(expr)),
567
+ expression=Expression(expr=str(phase_expr)),
540
568
  theta=Expression(expr=str(theta)),
541
569
  source_ref=source_ref,
542
570
  )
@@ -4,10 +4,8 @@ from typing import TYPE_CHECKING, Any, Optional
4
4
 
5
5
  from classiq.interface.exceptions import ClassiqError
6
6
  from classiq.interface.generator.expressions.expression import Expression
7
- from classiq.interface.generator.expressions.proxies.classical.any_classical_value import (
8
- AnyClassicalValue,
9
- )
10
7
 
8
+ from classiq.evaluators.qmod_annotated_expression import QmodAnnotatedExpression
11
9
  from classiq.qmod.cparam import CParamScalar
12
10
 
13
11
  if TYPE_CHECKING:
@@ -47,6 +45,6 @@ def get_frontend_interpreter() -> "GenerativeInterpreter":
47
45
 
48
46
  def interpret_expression(expr: str) -> Any:
49
47
  val = get_frontend_interpreter().evaluate(Expression(expr=expr)).value
50
- if isinstance(val, AnyClassicalValue):
48
+ if isinstance(val, QmodAnnotatedExpression):
51
49
  return CParamScalar(str(val))
52
50
  return val
@@ -312,7 +312,7 @@ class DSLPrettyPrinter(ModelVisitor):
312
312
  return control
313
313
 
314
314
  def visit_PhaseOperation(self, op: PhaseOperation) -> str:
315
- theta = f", {self.visit(op.theta)}" if op.theta else ""
315
+ theta = f", {self.visit(op.theta)}" if op.theta.expr != "1.0" else ""
316
316
  phase = f"{self._indent}phase ({self.visit(op.expression)}{theta});\n"
317
317
  return phase
318
318
 
@@ -461,7 +461,7 @@ class PythonPrettyPrinter(ModelVisitor):
461
461
 
462
462
  def visit_PhaseOperation(self, op: PhaseOperation) -> str:
463
463
  self._imports["phase"] = 1
464
- theta = f", {self.visit(op.theta)}" if op.theta is not None else ""
464
+ theta = f", {self.visit(op.theta)}" if op.theta.expr != "1.0" else ""
465
465
  return f"{self._indent}phase({self.visit(op.expression)}{theta})\n"
466
466
 
467
467
  def visit_ClassicalIf(self, op: ClassicalIf) -> str:
@@ -138,7 +138,7 @@ class QConstant(SymbolicExpr):
138
138
  f"Constant {self.name!r} of type {self._py_type.__name__!r} does not "
139
139
  f"have a 'len' property"
140
140
  )
141
- len_expr = f"get_field({self.name}, 'len')"
141
+ len_expr = f"{self.name}.len"
142
142
  if is_generative_mode():
143
143
  return interpret_expression(len_expr)
144
144
  return cast(int, CParamScalar(len_expr))
@@ -100,7 +100,7 @@ class CParamList(CParam):
100
100
  if is_generative_mode():
101
101
  with generative_mode_context(False):
102
102
  return interpret_expression(str(self.len))
103
- return CParamScalar(f"get_field({self}, 'len')")
103
+ return CParamScalar(f"{self}.len")
104
104
 
105
105
 
106
106
  class CParamStruct(CParam):
@@ -135,7 +135,7 @@ class CParamStruct(CParam):
135
135
  )
136
136
 
137
137
  return create_param(
138
- f"get_field({variable_name},{field_name!r})",
138
+ f"{variable_name}.{field_name}",
139
139
  field_type.model_copy(deep=True),
140
140
  qmodule=qmodule,
141
141
  )
@@ -156,7 +156,7 @@ class QVar(Symbolic):
156
156
  if is_generative_mode():
157
157
  with generative_mode_context(False):
158
158
  return interpret_expression(str(self.size))
159
- return CParamScalar(f"get_field({self}, 'size')")
159
+ return CParamScalar(f"{self}.size")
160
160
 
161
161
  @property
162
162
  def type_name(self) -> str:
@@ -229,8 +229,8 @@ class QScalar(QVar, SymbolicExpr):
229
229
 
230
230
  def __ior__(self, other: Any) -> Self:
231
231
  if not isinstance(other, SYMBOLIC_TYPES):
232
- raise TypeError(
233
- f"Invalid argument {other!r} for out-of-place arithmetic operation"
232
+ raise ClassiqValueError(
233
+ f"Invalid argument {str(other)!r} for out-of-place arithmetic operation"
234
234
  )
235
235
 
236
236
  self._insert_arith_operation(
@@ -240,8 +240,8 @@ class QScalar(QVar, SymbolicExpr):
240
240
 
241
241
  def __ixor__(self, other: Any) -> Self:
242
242
  if not isinstance(other, SYMBOLIC_TYPES):
243
- raise TypeError(
244
- f"Invalid argument {other!r} for in-place arithmetic operation"
243
+ raise ClassiqValueError(
244
+ f"Invalid argument {str(other)!r} for in-place arithmetic operation"
245
245
  )
246
246
 
247
247
  self._insert_arith_operation(
@@ -251,8 +251,8 @@ class QScalar(QVar, SymbolicExpr):
251
251
 
252
252
  def __iadd__(self, other: Any) -> Self:
253
253
  if not isinstance(other, SYMBOLIC_TYPES):
254
- raise TypeError(
255
- f"Invalid argument {other!r} for in-place arithmetic operation"
254
+ raise ClassiqValueError(
255
+ f"Invalid argument {str(other)!r} for in-place arithmetic operation"
256
256
  )
257
257
 
258
258
  self._insert_arith_operation(
@@ -262,8 +262,8 @@ class QScalar(QVar, SymbolicExpr):
262
262
 
263
263
  def __imul__(self, other: Any) -> Self:
264
264
  if not isinstance(other, SYMBOLIC_TYPES):
265
- raise TypeError(
266
- f"Invalid argument {other!r} for out of ampltiude encoding operation"
265
+ raise ClassiqValueError(
266
+ f"Invalid argument {str(other)!r} for out of ampltiude encoding operation"
267
267
  )
268
268
 
269
269
  self._insert_amplitude_loading(other, get_source_ref(sys._getframe(1)))
@@ -432,7 +432,7 @@ class QNum(Generic[_P], QScalar):
432
432
  name: Union[None, str, HandleBinding] = None,
433
433
  size: Union[int, CInt, Expression, SymbolicExpr, None] = None,
434
434
  is_signed: Union[bool, CBool, Expression, SymbolicExpr, None] = None,
435
- fraction_digits: Union[int, CInt, Expression, None] = None,
435
+ fraction_digits: Union[int, CInt, Expression, SymbolicExpr, None] = None,
436
436
  _expr_str: Optional[str] = None,
437
437
  ):
438
438
  if size is None and (is_signed is not None or fraction_digits is not None):
@@ -485,14 +485,14 @@ class QNum(Generic[_P], QScalar):
485
485
  if is_generative_mode():
486
486
  with generative_mode_context(False):
487
487
  return interpret_expression(str(self.fraction_digits))
488
- return CParamScalar(f"get_field({self}, 'fraction_digits')")
488
+ return CParamScalar(f"{self}.fraction_digits")
489
489
 
490
490
  @property
491
491
  def is_signed(self) -> Union[CParamScalar, bool]:
492
492
  if is_generative_mode():
493
493
  with generative_mode_context(False):
494
494
  return interpret_expression(str(self.is_signed))
495
- return CParamScalar(f"get_field({self}, 'is_signed')")
495
+ return CParamScalar(f"{self}.is_signed")
496
496
 
497
497
  def get_maximal_bounds(self) -> tuple[float, float]:
498
498
  if not is_generative_mode():
@@ -594,7 +594,7 @@ class QArray(ArrayBase[_P], QVar, NonSymbolicExpr):
594
594
  if is_generative_mode():
595
595
  with generative_mode_context(False):
596
596
  return interpret_expression(str(self.len))
597
- return CParamScalar(f"get_field({self}, 'len')")
597
+ return CParamScalar(f"{self}.len")
598
598
 
599
599
  @classmethod
600
600
  def to_qvar(
@@ -669,7 +669,7 @@ class QStruct(QVar):
669
669
  field_name: field_class.to_qvar(
670
670
  FieldHandleBinding(base_handle=base_handle, field=field_name),
671
671
  field_type,
672
- f"get_field({expr_str if expr_str is not None else str(origin)}, '{field_name}')",
672
+ f"{expr_str if expr_str is not None else str(origin)}.{field_name}",
673
673
  )
674
674
  for field_name, (field_class, field_type) in field_types.items()
675
675
  }
@@ -723,7 +723,7 @@ def _create_qvar_for_qtype(
723
723
  field_name: _create_qvar_for_qtype(
724
724
  field_type,
725
725
  FieldHandleBinding(base_handle=origin, field=field_name),
726
- f"get_field({expr_str if expr_str is not None else str(origin)}, '{field_name}')",
726
+ f"{expr_str if expr_str is not None else str(origin)}.{field_name}",
727
727
  )
728
728
  for field_name, field_type in struct_decl.fields.items()
729
729
  },
@@ -286,7 +286,7 @@ class QTerminalCallable(QCallable):
286
286
  def len(self) -> CParamScalar:
287
287
  if not self.is_list:
288
288
  raise ClassiqValueError("Cannot get length of a non-list operand")
289
- return CParamScalar(f"get_field({self.func_decl.name}, 'len')")
289
+ return CParamScalar(f"{self.func_decl.name}.len")
290
290
 
291
291
  @property
292
292
  def func_decl(self) -> QuantumFunctionDeclaration:
classiq/synthesis.py CHANGED
@@ -1,10 +1,14 @@
1
1
  from typing import Any, Optional, Union
2
2
 
3
- from classiq.interface.analyzer.result import QasmCode
3
+ from classiq.interface.analyzer.result import QasmCode, QmodCode
4
4
  from classiq.interface.exceptions import ClassiqError, ClassiqValueError
5
5
  from classiq.interface.executor.execution_preferences import ExecutionPreferences
6
6
  from classiq.interface.generator.model.constraints import Constraints
7
7
  from classiq.interface.generator.model.preferences.preferences import Preferences
8
+ from classiq.interface.generator.preferences.qasm_to_qmod_params import (
9
+ QasmToQmodParams,
10
+ QmodFormat,
11
+ )
8
12
  from classiq.interface.model.model import MAIN_FUNCTION_NAME, Model, SerializedModel
9
13
 
10
14
  from classiq import QuantumProgram
@@ -87,12 +91,43 @@ def synthesize(
87
91
  serialized_model = model_obj.get_model()
88
92
  else:
89
93
  serialized_model = model
94
+ if preferences is not None:
95
+ serialized_model = set_preferences(
96
+ serialized_model, preferences=preferences
97
+ )
98
+ if constraints is not None:
99
+ serialized_model = set_constraints(
100
+ serialized_model, constraints=constraints
101
+ )
90
102
  result = async_utils.run(synthesize_async(serialized_model))
91
103
  if auto_show:
92
104
  show(result)
93
105
  return result
94
106
 
95
107
 
108
+ async def qasm_to_qmod_async(params: QasmToQmodParams) -> QmodCode:
109
+ return await ApiWrapper.call_qasm_to_qmod_task(params)
110
+
111
+
112
+ def qasm_to_qmod(qasm: str, qmod_format: QmodFormat) -> str:
113
+ """
114
+ Decompiles QASM to Native/Python Qmod.
115
+
116
+ Args:
117
+ qasm: QASM 2 or QASM 3 code
118
+ qmod_format: The requested output format
119
+
120
+ Returns:
121
+ The decompiled Qmod program
122
+ """
123
+
124
+ return async_utils.run(
125
+ qasm_to_qmod_async(
126
+ QasmToQmodParams(qasm=QasmCode(code=qasm), qmod_format=qmod_format)
127
+ )
128
+ ).code
129
+
130
+
96
131
  def set_preferences(
97
132
  serialized_model: SerializedModel,
98
133
  preferences: Optional[Preferences] = None,
@@ -241,6 +276,7 @@ def update_execution_preferences(
241
276
 
242
277
  __all__ = [
243
278
  "SerializedModel",
279
+ "qasm_to_qmod",
244
280
  "set_constraints",
245
281
  "set_execution_preferences",
246
282
  "set_preferences",
classiq/visualization.py CHANGED
@@ -19,7 +19,7 @@ async def visualize_async(
19
19
  raise error
20
20
  analyzer_data = await ApiWrapper.get_analyzer_app_data(data_id)
21
21
  visual_model = await ApiWrapper.call_visualization_task(analyzer_data)
22
- return SerializedVisualModel(visual_model.model_dump_json(indent=2))
22
+ return SerializedVisualModel(visual_model.model_dump_json())
23
23
 
24
24
 
25
25
  def visualize(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: classiq
3
- Version: 0.89.0
3
+ Version: 0.90.0
4
4
  Summary: Classiq's Python SDK for quantum computing
5
5
  License: Proprietary
6
6
  Keywords: quantum computing,quantum circuits,quantum algorithms,QAD,QDL