classiq 0.86.1__py3-none-any.whl → 0.88.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 (131) hide show
  1. classiq/__init__.py +2 -0
  2. classiq/applications/__init__.py +1 -2
  3. classiq/applications/chemistry/hartree_fock.py +5 -1
  4. classiq/applications/chemistry/op_utils.py +2 -2
  5. classiq/applications/combinatorial_helpers/combinatorial_problem_utils.py +1 -1
  6. classiq/applications/combinatorial_helpers/encoding_mapping.py +11 -15
  7. classiq/applications/combinatorial_helpers/encoding_utils.py +6 -6
  8. classiq/applications/combinatorial_helpers/memory.py +4 -4
  9. classiq/applications/combinatorial_helpers/optimization_model.py +5 -5
  10. classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +6 -10
  11. classiq/applications/combinatorial_helpers/pyomo_utils.py +27 -26
  12. classiq/applications/combinatorial_helpers/sympy_utils.py +2 -2
  13. classiq/applications/combinatorial_helpers/transformations/encoding.py +4 -6
  14. classiq/applications/combinatorial_helpers/transformations/fixed_variables.py +4 -4
  15. classiq/applications/combinatorial_helpers/transformations/ising_converter.py +2 -2
  16. classiq/applications/combinatorial_helpers/transformations/penalty_support.py +3 -3
  17. classiq/applications/combinatorial_optimization/combinatorial_problem.py +4 -0
  18. classiq/applications/hamiltonian/pauli_decomposition.py +34 -2
  19. classiq/evaluators/argument_types.py +15 -6
  20. classiq/evaluators/parameter_types.py +43 -39
  21. classiq/evaluators/qmod_annotated_expression.py +117 -17
  22. classiq/evaluators/qmod_expression_visitors/out_of_place_node_transformer.py +19 -0
  23. classiq/evaluators/qmod_expression_visitors/qmod_expression_bwc.py +0 -5
  24. classiq/evaluators/qmod_expression_visitors/qmod_expression_evaluator.py +66 -16
  25. classiq/evaluators/qmod_expression_visitors/qmod_expression_renamer.py +48 -26
  26. classiq/evaluators/qmod_expression_visitors/qmod_expression_simplifier.py +65 -72
  27. classiq/evaluators/qmod_node_evaluators/attribute_evaluation.py +13 -6
  28. classiq/evaluators/qmod_node_evaluators/binary_op_evaluation.py +175 -28
  29. classiq/evaluators/qmod_node_evaluators/classical_function_evaluation.py +36 -19
  30. classiq/evaluators/qmod_node_evaluators/compare_evaluation.py +17 -5
  31. classiq/evaluators/qmod_node_evaluators/constant_evaluation.py +24 -2
  32. classiq/evaluators/qmod_node_evaluators/min_max_evaluation.py +97 -0
  33. classiq/evaluators/qmod_node_evaluators/name_evaluation.py +11 -26
  34. classiq/evaluators/qmod_node_evaluators/numeric_attrs_utils.py +56 -0
  35. classiq/evaluators/qmod_node_evaluators/piecewise_evaluation.py +40 -0
  36. classiq/evaluators/qmod_node_evaluators/struct_instantiation_evaluation.py +3 -4
  37. classiq/evaluators/qmod_node_evaluators/subscript_evaluation.py +51 -24
  38. classiq/evaluators/qmod_node_evaluators/unary_op_evaluation.py +53 -9
  39. classiq/evaluators/qmod_node_evaluators/utils.py +28 -6
  40. classiq/evaluators/qmod_type_inference/classical_type_inference.py +188 -0
  41. classiq/evaluators/qmod_type_inference/quantum_type_inference.py +330 -0
  42. classiq/evaluators/quantum_type_utils.py +0 -131
  43. classiq/evaluators/type_type_match.py +1 -1
  44. classiq/execution/execution_session.py +18 -3
  45. classiq/execution/qnn.py +4 -1
  46. classiq/execution/user_budgets.py +1 -1
  47. classiq/interface/_version.py +1 -1
  48. classiq/interface/backend/backend_preferences.py +10 -30
  49. classiq/interface/backend/quantum_backend_providers.py +63 -52
  50. classiq/interface/execution/primitives.py +1 -0
  51. classiq/interface/generator/application_apis/__init__.py +0 -1
  52. classiq/interface/generator/arith/binary_ops.py +107 -115
  53. classiq/interface/generator/arith/extremum_operations.py +33 -45
  54. classiq/interface/generator/arith/number_utils.py +4 -1
  55. classiq/interface/generator/circuit_code/types_and_constants.py +0 -9
  56. classiq/interface/generator/compiler_keywords.py +2 -0
  57. classiq/interface/generator/expressions/atomic_expression_functions.py +0 -2
  58. classiq/interface/generator/function_param_list.py +129 -5
  59. classiq/interface/generator/functions/classical_type.py +67 -2
  60. classiq/interface/generator/functions/qmod_python_interface.py +15 -0
  61. classiq/interface/generator/functions/type_name.py +12 -0
  62. classiq/interface/generator/model/preferences/preferences.py +1 -17
  63. classiq/interface/generator/quantum_program.py +1 -13
  64. classiq/interface/generator/transpiler_basis_gates.py +5 -1
  65. classiq/interface/generator/types/builtin_enum_declarations.py +0 -8
  66. classiq/interface/helpers/model_normalizer.py +2 -2
  67. classiq/interface/helpers/text_utils.py +7 -2
  68. classiq/interface/interface_version.py +1 -1
  69. classiq/interface/model/classical_if.py +48 -0
  70. classiq/interface/model/classical_parameter_declaration.py +4 -0
  71. classiq/interface/model/handle_binding.py +28 -16
  72. classiq/interface/model/port_declaration.py +12 -0
  73. classiq/interface/model/quantum_function_declaration.py +12 -0
  74. classiq/interface/model/quantum_type.py +117 -2
  75. classiq/interface/pretty_print/expression_to_qmod.py +7 -8
  76. classiq/interface/pyomo_extension/__init__.py +0 -4
  77. classiq/interface/pyomo_extension/pyomo_sympy_bimap.py +2 -2
  78. classiq/model_expansions/arithmetic.py +43 -1
  79. classiq/model_expansions/arithmetic_compute_result_attrs.py +255 -0
  80. classiq/model_expansions/capturing/captured_vars.py +2 -5
  81. classiq/model_expansions/quantum_operations/allocate.py +23 -16
  82. classiq/model_expansions/quantum_operations/arithmetic/explicit_boolean_expressions.py +1 -3
  83. classiq/model_expansions/quantum_operations/assignment_result_processor.py +52 -71
  84. classiq/model_expansions/quantum_operations/bind.py +15 -7
  85. classiq/model_expansions/quantum_operations/call_emitter.py +2 -10
  86. classiq/model_expansions/quantum_operations/classical_var_emitter.py +6 -0
  87. classiq/model_expansions/quantum_operations/handle_evaluator.py +2 -8
  88. classiq/open_library/functions/__init__.py +4 -0
  89. classiq/open_library/functions/lcu.py +117 -0
  90. classiq/open_library/functions/state_preparation.py +47 -5
  91. classiq/qmod/builtins/__init__.py +0 -3
  92. classiq/qmod/builtins/classical_functions.py +0 -28
  93. classiq/qmod/builtins/enums.py +26 -20
  94. classiq/qmod/builtins/functions/__init__.py +0 -5
  95. classiq/qmod/builtins/operations.py +142 -0
  96. classiq/qmod/builtins/structs.py +33 -29
  97. classiq/qmod/native/pretty_printer.py +1 -1
  98. classiq/qmod/pretty_print/expression_to_python.py +1 -6
  99. classiq/qmod/pretty_print/pretty_printer.py +4 -1
  100. classiq/qmod/qmod_variable.py +94 -2
  101. classiq/qmod/semantics/annotation/call_annotation.py +4 -2
  102. classiq/qmod/semantics/annotation/qstruct_annotator.py +20 -5
  103. {classiq-0.86.1.dist-info → classiq-0.88.0.dist-info}/METADATA +5 -5
  104. {classiq-0.86.1.dist-info → classiq-0.88.0.dist-info}/RECORD +106 -124
  105. classiq/applications/finance/__init__.py +0 -15
  106. classiq/interface/finance/finance_modelling_params.py +0 -11
  107. classiq/interface/finance/function_input.py +0 -102
  108. classiq/interface/finance/gaussian_model_input.py +0 -50
  109. classiq/interface/finance/log_normal_model_input.py +0 -40
  110. classiq/interface/finance/model_input.py +0 -22
  111. classiq/interface/generator/amplitude_estimation.py +0 -34
  112. classiq/interface/generator/application_apis/finance_declarations.py +0 -108
  113. classiq/interface/generator/expressions/enums/__init__.py +0 -0
  114. classiq/interface/generator/expressions/enums/finance_functions.py +0 -12
  115. classiq/interface/generator/finance.py +0 -107
  116. classiq/interface/generator/function_param_list_without_self_reference.py +0 -160
  117. classiq/interface/generator/grover_diffuser.py +0 -93
  118. classiq/interface/generator/grover_operator.py +0 -106
  119. classiq/interface/generator/oracles/__init__.py +0 -3
  120. classiq/interface/generator/oracles/arithmetic_oracle.py +0 -82
  121. classiq/interface/generator/oracles/custom_oracle.py +0 -65
  122. classiq/interface/generator/oracles/oracle_abc.py +0 -76
  123. classiq/interface/generator/oracles/oracle_function_param_list.py +0 -6
  124. classiq/interface/generator/piecewise_linear_amplitude_loading.py +0 -165
  125. classiq/interface/generator/qpe.py +0 -169
  126. classiq/interface/grover/__init__.py +0 -0
  127. classiq/interface/grover/grover_modelling_params.py +0 -13
  128. classiq/model_expansions/transformers/var_splitter.py +0 -224
  129. classiq/qmod/builtins/functions/finance.py +0 -34
  130. /classiq/{interface/finance → evaluators/qmod_type_inference}/__init__.py +0 -0
  131. {classiq-0.86.1.dist-info → classiq-0.88.0.dist-info}/WHEEL +0 -0
@@ -36,6 +36,14 @@ from classiq.model_expansions.arithmetic import NumericAttributes
36
36
  from classiq.model_expansions.arithmetic_compute_result_attrs import (
37
37
  compute_result_attrs_add,
38
38
  compute_result_attrs_assign,
39
+ compute_result_attrs_bitwise_and,
40
+ compute_result_attrs_bitwise_or,
41
+ compute_result_attrs_bitwise_xor,
42
+ compute_result_attrs_lshift,
43
+ compute_result_attrs_modulo,
44
+ compute_result_attrs_multiply,
45
+ compute_result_attrs_power,
46
+ compute_result_attrs_rshift,
39
47
  compute_result_attrs_subtract,
40
48
  )
41
49
 
@@ -225,31 +233,6 @@ class BinaryOpWithIntInputs(BinaryOpParams[RegisterOrInt, RegisterOrInt]):
225
233
  raise ClassiqValueError(BOOLEAN_OP_WITH_FRACTIONS_ERROR)
226
234
  return self
227
235
 
228
- @staticmethod
229
- def _is_signed(arg: Union[int, RegisterArithmeticInfo]) -> bool:
230
- if isinstance(arg, RegisterArithmeticInfo):
231
- return arg.is_signed
232
- return arg < 0
233
-
234
- def _get_result_register(self) -> RegisterArithmeticInfo:
235
- required_size = self._aligned_inputs_max_length()
236
- is_signed = self._include_sign and (
237
- self._is_signed(self.left_arg) or self._is_signed(self.right_arg)
238
- )
239
- return RegisterArithmeticInfo(
240
- size=self.output_size or required_size, is_signed=is_signed
241
- )
242
-
243
- def _aligned_inputs_max_length(self) -> int:
244
- left_signed: bool = argument_utils.is_signed(self.left_arg)
245
- right_signed: bool = argument_utils.is_signed(self.right_arg)
246
- return max(
247
- argument_utils.integer_part_size(self.right_arg)
248
- + int(left_signed and not right_signed),
249
- argument_utils.integer_part_size(self.left_arg)
250
- + int(right_signed and not left_signed),
251
- )
252
-
253
236
 
254
237
  class BinaryOpWithFloatInputs(BinaryOpParams[RegisterOrConst, RegisterOrConst]):
255
238
  pass
@@ -258,10 +241,42 @@ class BinaryOpWithFloatInputs(BinaryOpParams[RegisterOrConst, RegisterOrConst]):
258
241
  class BitwiseAnd(BinaryOpWithIntInputs):
259
242
  output_name = "bitwise_and"
260
243
 
244
+ def _get_result_register(self) -> RegisterArithmeticInfo:
245
+ left_attrs = NumericAttributes.from_type_or_constant(
246
+ self.left_arg, self.machine_precision
247
+ )
248
+ right_attrs = NumericAttributes.from_type_or_constant(
249
+ self.right_arg, self.machine_precision
250
+ )
251
+ result_attrs = compute_result_attrs_bitwise_and(
252
+ left_attrs, right_attrs, self.machine_precision
253
+ )
254
+ return RegisterArithmeticInfo(
255
+ size=self.output_size or result_attrs.size,
256
+ is_signed=self._include_sign and result_attrs.is_signed,
257
+ fraction_places=result_attrs.fraction_digits,
258
+ )
259
+
261
260
 
262
261
  class BitwiseOr(BinaryOpWithIntInputs):
263
262
  output_name = "bitwise_or"
264
263
 
264
+ def _get_result_register(self) -> RegisterArithmeticInfo:
265
+ left_attrs = NumericAttributes.from_type_or_constant(
266
+ self.left_arg, self.machine_precision
267
+ )
268
+ right_attrs = NumericAttributes.from_type_or_constant(
269
+ self.right_arg, self.machine_precision
270
+ )
271
+ result_attrs = compute_result_attrs_bitwise_or(
272
+ left_attrs, right_attrs, self.machine_precision
273
+ )
274
+ return RegisterArithmeticInfo(
275
+ size=self.output_size or result_attrs.size,
276
+ is_signed=self._include_sign and result_attrs.is_signed,
277
+ fraction_places=result_attrs.fraction_digits,
278
+ )
279
+
265
280
 
266
281
  # TODO: fix diamond inheritance
267
282
  class BitwiseXor(
@@ -269,6 +284,22 @@ class BitwiseXor(
269
284
  ):
270
285
  output_name = "bitwise_xor"
271
286
 
287
+ def _get_result_register(self) -> RegisterArithmeticInfo:
288
+ left_attrs = NumericAttributes.from_type_or_constant(
289
+ self.left_arg, self.machine_precision
290
+ )
291
+ right_attrs = NumericAttributes.from_type_or_constant(
292
+ self.right_arg, self.machine_precision
293
+ )
294
+ result_attrs = compute_result_attrs_bitwise_xor(
295
+ left_attrs, right_attrs, self.machine_precision
296
+ )
297
+ return RegisterArithmeticInfo(
298
+ size=self.output_size or result_attrs.size,
299
+ is_signed=self._include_sign and result_attrs.is_signed,
300
+ fraction_places=result_attrs.fraction_digits,
301
+ )
302
+
272
303
 
273
304
  class Adder(InplacableBinaryOpParams[RegisterOrConst, RegisterOrConst]):
274
305
  output_name = "sum"
@@ -467,29 +498,18 @@ class Multiplier(BinaryOpWithFloatInputs):
467
498
  argument_utils.limit_fraction_places(self.right_arg, self.machine_precision)
468
499
  )
469
500
 
470
- @staticmethod
471
- def _get_bounds(
472
- args: tuple[RegisterOrConst, RegisterOrConst], machine_precision: int
473
- ) -> tuple[float, float]:
474
- extremal_values = [
475
- left * right
476
- for left in argument_utils.bounds(args[0])
477
- for right in argument_utils.bounds(args[1])
478
- ]
479
- return (
480
- number_utils.limit_fraction_places(min(extremal_values), machine_precision),
481
- number_utils.limit_fraction_places(max(extremal_values), machine_precision),
482
- )
483
-
484
501
  def _get_result_register(self) -> RegisterArithmeticInfo:
485
- fraction_places = min(self.machine_precision, self.expected_fraction_places())
486
- left_arg = argument_utils.limit_fraction_places(
502
+ left_attrs = NumericAttributes.from_type_or_constant(
487
503
  self.left_arg, self.machine_precision
488
504
  )
489
- right_arg = argument_utils.limit_fraction_places(
505
+ right_attrs = NumericAttributes.from_type_or_constant(
490
506
  self.right_arg, self.machine_precision
491
507
  )
492
- bounds = self._get_bounds((left_arg, right_arg), self.machine_precision)
508
+ result_attrs = compute_result_attrs_multiply(
509
+ left_attrs, right_attrs, self.machine_precision
510
+ )
511
+ fraction_places = result_attrs.fraction_digits
512
+ bounds = result_attrs.bounds
493
513
  if self.output_size:
494
514
  if fraction_places:
495
515
  raise ValueError(MODULO_WITH_FRACTION_PLACES_ERROR_MSG)
@@ -498,10 +518,8 @@ class Multiplier(BinaryOpWithFloatInputs):
498
518
  )
499
519
  bounds = number_utils.bounds_cut(bounds, max_bounds)
500
520
 
501
- size = self.output_size or self._get_output_size(
502
- bounds, fraction_places, left_arg, right_arg
503
- )
504
- is_signed = self._include_sign and min(bounds) < 0
521
+ size = self.output_size or result_attrs.size
522
+ is_signed = self._include_sign and result_attrs.is_signed
505
523
  return RegisterArithmeticInfo(
506
524
  size=size,
507
525
  fraction_places=fraction_places,
@@ -514,25 +532,6 @@ class Multiplier(BinaryOpWithFloatInputs):
514
532
  ),
515
533
  )
516
534
 
517
- @staticmethod
518
- def _get_output_size(
519
- bounds: tuple[float, float],
520
- fraction_places: int,
521
- left_arg: Union[RegisterArithmeticInfo, float],
522
- right_arg: Union[RegisterArithmeticInfo, float],
523
- ) -> int:
524
- if isinstance(left_arg, float) and left_arg == 1.0:
525
- assert isinstance(right_arg, RegisterArithmeticInfo)
526
- return right_arg.size
527
- elif isinstance(right_arg, float) and right_arg == 1.0:
528
- assert isinstance(left_arg, RegisterArithmeticInfo)
529
- return left_arg.size
530
- if bounds[0] == 0 and bounds[1] == 0:
531
- return max(1, fraction_places)
532
-
533
- integer_part_size = number_utils.bounds_to_integer_part_size(*bounds)
534
- return integer_part_size + fraction_places
535
-
536
535
  def garbage_output_size(self) -> pydantic.NonNegativeInt:
537
536
  return max(
538
537
  0, self.expected_fraction_places() - self.result_register.fraction_places
@@ -592,43 +591,22 @@ class Power(BinaryOpParams[RegisterArithmeticInfo, pydantic.PositiveInt]):
592
591
  * self.right_arg
593
592
  )
594
593
 
595
- def _get_result_bounds(self) -> tuple[float, float]:
596
- bounds = [
597
- number_utils.limit_fraction_places(
598
- bound, machine_precision=self.machine_precision
599
- )
600
- for bound in self.left_arg.bounds
601
- ]
602
- if (self.right_arg % 2) or min(bounds) >= 0 or max(bounds) <= 0:
603
- return (
604
- number_utils.limit_fraction_places(
605
- bounds[0] ** self.right_arg,
606
- machine_precision=self.machine_precision,
607
- ),
608
- number_utils.limit_fraction_places(
609
- bounds[1] ** self.right_arg,
610
- machine_precision=self.machine_precision,
611
- ),
612
- )
613
- return 0.0, number_utils.limit_fraction_places(
614
- max(abs(bound) for bound in bounds) ** self.right_arg,
615
- machine_precision=self.machine_precision,
616
- )
617
-
618
594
  def _get_result_register(self) -> RegisterArithmeticInfo:
619
595
  if self.output_size:
620
596
  return RegisterArithmeticInfo(size=self.output_size)
621
597
 
622
- fraction_places = min(self.machine_precision, self.expected_fraction_places())
623
- bounds = self._get_result_bounds()
624
- size = number_utils.bounds_to_integer_part_size(*bounds) + fraction_places
625
- if bounds[0] == 0 and bounds[1] == 0:
626
- size = max(1, fraction_places)
598
+ left_attrs = NumericAttributes.from_register_arithmetic_info(
599
+ self.left_arg, self.machine_precision
600
+ )
601
+ result_attrs = compute_result_attrs_power(
602
+ left_attrs, self.right_arg, self.machine_precision
603
+ )
604
+
627
605
  return RegisterArithmeticInfo(
628
- size=size,
629
- is_signed=self.left_arg.is_signed and (self.right_arg % 2 == 1),
630
- fraction_places=fraction_places,
631
- bounds=bounds,
606
+ size=result_attrs.size,
607
+ is_signed=result_attrs.is_signed,
608
+ fraction_places=result_attrs.fraction_digits,
609
+ bounds=result_attrs.bounds,
632
610
  )
633
611
 
634
612
  def _get_inner_action_garbage_size(
@@ -709,13 +687,17 @@ class LShift(EffectiveUnaryOpParams[pydantic.NonNegativeInt]):
709
687
  return max(self.left_arg.size + extra_result_lsbs - self.output_size, 0)
710
688
 
711
689
  def _get_result_register(self) -> RegisterArithmeticInfo:
712
- new_fraction_places = max(self.left_arg.fraction_places - self.right_arg, 0)
713
- new_integer_part_size = self.left_arg.integer_part_size + self.right_arg
714
- required_size = new_integer_part_size + new_fraction_places
690
+ left_attrs = NumericAttributes.from_register_arithmetic_info(
691
+ self.left_arg, self.machine_precision
692
+ )
693
+ result_attrs = compute_result_attrs_lshift(
694
+ left_attrs, self.right_arg, self.machine_precision
695
+ )
715
696
  return RegisterArithmeticInfo(
716
- size=self.output_size or required_size,
717
- is_signed=self._include_sign and self.left_arg.is_signed,
718
- fraction_places=new_fraction_places,
697
+ size=self.output_size or result_attrs.size,
698
+ is_signed=self._include_sign and result_attrs.is_signed,
699
+ fraction_places=result_attrs.fraction_digits,
700
+ bounds=result_attrs.bounds if not self.output_size else None,
719
701
  )
720
702
 
721
703
 
@@ -755,15 +737,17 @@ class RShift(EffectiveUnaryOpParams[pydantic.NonNegativeInt]):
755
737
  )
756
738
 
757
739
  def _get_result_register(self) -> RegisterArithmeticInfo:
758
- min_size: int = max(self.left_arg.size - self.right_arg, 1)
759
- new_fraction_places = self._shifted_fraction_places(
760
- arg=self.left_arg, shift=self.right_arg
740
+ left_attrs = NumericAttributes.from_register_arithmetic_info(
741
+ self.left_arg, self.machine_precision
742
+ )
743
+ result_attrs = compute_result_attrs_rshift(
744
+ left_attrs, self.right_arg, self.machine_precision
761
745
  )
762
- required_size = max(min_size, new_fraction_places)
763
746
  return RegisterArithmeticInfo(
764
- size=self.output_size or required_size,
765
- is_signed=self._include_sign and self.left_arg.is_signed,
766
- fraction_places=new_fraction_places,
747
+ size=self.output_size or result_attrs.size,
748
+ is_signed=self._include_sign and result_attrs.is_signed,
749
+ fraction_places=result_attrs.fraction_digits,
750
+ bounds=result_attrs.bounds if not self.output_size else None,
767
751
  )
768
752
 
769
753
 
@@ -822,7 +806,15 @@ class Modulo(EffectiveUnaryOpParams[int]):
822
806
  return 2 ** (repr_qubits)
823
807
 
824
808
  def _get_result_register(self) -> RegisterArithmeticInfo:
825
- size = round(math.log2(self.right_arg))
826
- if size <= 0:
827
- raise ClassiqValueError("Cannot use a quantum expression with zero size")
828
- return RegisterArithmeticInfo(size=size, is_signed=False, fraction_places=0)
809
+ left_attrs = NumericAttributes.from_register_arithmetic_info(
810
+ self.left_arg, self.machine_precision
811
+ )
812
+ result_attrs = compute_result_attrs_modulo(
813
+ left_attrs, self.right_arg, self.machine_precision
814
+ )
815
+ return RegisterArithmeticInfo(
816
+ size=result_attrs.size,
817
+ is_signed=result_attrs.is_signed,
818
+ fraction_places=result_attrs.fraction_digits,
819
+ bounds=result_attrs.bounds,
820
+ )
@@ -18,6 +18,12 @@ from classiq.interface.generator.arith.binary_ops import (
18
18
  from classiq.interface.generator.arith.register_user_input import RegisterArithmeticInfo
19
19
  from classiq.interface.generator.function_params import get_zero_input_name
20
20
 
21
+ from classiq.model_expansions.arithmetic import NumericAttributes
22
+ from classiq.model_expansions.arithmetic_compute_result_attrs import (
23
+ compute_result_attrs_max,
24
+ compute_result_attrs_min,
25
+ )
26
+
21
27
  Numeric = (float, int)
22
28
 
23
29
 
@@ -55,11 +61,6 @@ class Extremum(ArithmeticOperationParams):
55
61
  def get_params_inplace_options(self) -> Iterable["Extremum"]:
56
62
  return ()
57
63
 
58
- @classmethod
59
- @abc.abstractmethod
60
- def _bound_calculator(cls, arg1: float, arg2: float) -> float:
61
- pass
62
-
63
64
  @staticmethod
64
65
  def _less_qubits_arg(
65
66
  arg1: RegisterOrConst, arg2: RegisterOrConst
@@ -78,40 +79,15 @@ class Extremum(ArithmeticOperationParams):
78
79
  pass
79
80
 
80
81
  def _get_result_register(self) -> RegisterArithmeticInfo:
81
- eff_left_arg = argument_utils.limit_fraction_places(
82
+ left_attrs = NumericAttributes.from_type_or_constant(
82
83
  self.left_arg, self.machine_precision
83
84
  )
84
- eff_right_arg = argument_utils.limit_fraction_places(
85
+ right_attrs = NumericAttributes.from_type_or_constant(
85
86
  self.right_arg, self.machine_precision
86
87
  )
87
- if argument_utils.arg_bounds_overlap((eff_left_arg, eff_right_arg)):
88
- return self._get_general_case_result_register(eff_left_arg, eff_right_arg)
89
- return argument_utils.as_arithmetic_info(
90
- self.preferred_arg(eff_left_arg, eff_right_arg)
91
- )
92
-
93
- def _get_general_case_result_register(
94
- self, eff_left_arg: RegisterOrConst, eff_right_arg: RegisterOrConst
95
- ) -> RegisterArithmeticInfo:
96
- integer_part_size = max(
97
- argument_utils.integer_part_size(eff_left_arg),
98
- argument_utils.integer_part_size(eff_right_arg),
99
- )
100
- fraction_places = max(
101
- argument_utils.fraction_places(eff_left_arg),
102
- argument_utils.fraction_places(eff_right_arg),
103
- )
104
- required_size = integer_part_size + fraction_places
105
- bounds = (
106
- self._bound_calculator(
107
- argument_utils.lower_bound(eff_left_arg),
108
- argument_utils.lower_bound(eff_right_arg),
109
- ),
110
- self._bound_calculator(
111
- argument_utils.upper_bound(eff_left_arg),
112
- argument_utils.upper_bound(eff_right_arg),
113
- ),
114
- )
88
+ result_attrs = self._compute_result_attrs(left_attrs, right_attrs)
89
+ bounds = result_attrs.bounds
90
+ fraction_places = result_attrs.fraction_digits
115
91
  if self.output_size:
116
92
  if fraction_places:
117
93
  raise ValueError(MODULO_WITH_FRACTION_PLACES_ERROR_MSG)
@@ -119,8 +95,8 @@ class Extremum(ArithmeticOperationParams):
119
95
  size=self.output_size, is_signed=False, fraction_places=0
120
96
  )
121
97
  bounds = number_utils.bounds_cut(bounds, max_bounds)
122
- size = self.output_size or required_size
123
- is_signed = self._include_sign and min(bounds) < 0
98
+ size = self.output_size or result_attrs.size
99
+ is_signed = self._include_sign and result_attrs.is_signed
124
100
  return RegisterArithmeticInfo(
125
101
  size=size,
126
102
  fraction_places=fraction_places,
@@ -133,14 +109,16 @@ class Extremum(ArithmeticOperationParams):
133
109
  ),
134
110
  )
135
111
 
112
+ @abc.abstractmethod
113
+ def _compute_result_attrs(
114
+ self, left_attrs: NumericAttributes, right_attrs: NumericAttributes
115
+ ) -> NumericAttributes:
116
+ pass
117
+
136
118
 
137
119
  class Min(Extremum):
138
120
  output_name = "min_value"
139
121
 
140
- @classmethod
141
- def _bound_calculator(cls, arg1: float, arg2: float) -> float:
142
- return min(arg1, arg2)
143
-
144
122
  @classmethod
145
123
  def preferred_arg(
146
124
  cls, arg1: RegisterOrConst, arg2: RegisterOrConst
@@ -152,14 +130,17 @@ class Min(Extremum):
152
130
  return arg2
153
131
  return cls._less_qubits_arg(arg1, arg2)
154
132
 
133
+ def _compute_result_attrs(
134
+ self, left_attrs: NumericAttributes, right_attrs: NumericAttributes
135
+ ) -> NumericAttributes:
136
+ return compute_result_attrs_min(
137
+ [left_attrs, right_attrs], self.machine_precision
138
+ )
139
+
155
140
 
156
141
  class Max(Extremum):
157
142
  output_name = "max_value"
158
143
 
159
- @classmethod
160
- def _bound_calculator(cls, arg1: float, arg2: float) -> float:
161
- return max(arg1, arg2)
162
-
163
144
  @classmethod
164
145
  def preferred_arg(
165
146
  cls, arg1: RegisterOrConst, arg2: RegisterOrConst
@@ -170,3 +151,10 @@ class Max(Extremum):
170
151
  if max2 > max1:
171
152
  return arg2
172
153
  return cls._less_qubits_arg(arg1, arg2)
154
+
155
+ def _compute_result_attrs(
156
+ self, left_attrs: NumericAttributes, right_attrs: NumericAttributes
157
+ ) -> NumericAttributes:
158
+ return compute_result_attrs_max(
159
+ [left_attrs, right_attrs], self.machine_precision
160
+ )
@@ -105,7 +105,10 @@ def bounds_to_attributes(
105
105
  lb: float, ub: float, fraction_places: int, machine_precision: int
106
106
  ) -> tuple[int, bool, int]:
107
107
  fraction_places = min(fraction_places, machine_precision)
108
- integers = bounds_to_integer_part_size(lb, ub)
108
+ if lb == ub == 0:
109
+ integers = 0
110
+ else:
111
+ integers = bounds_to_integer_part_size(lb, ub)
109
112
  return max(1, integers + fraction_places), lb < 0, fraction_places
110
113
 
111
114
 
@@ -3,7 +3,6 @@ from typing_extensions import TypeAlias
3
3
  from classiq.interface.enum_utils import StrEnum
4
4
  from classiq.interface.executor.quantum_instruction_set import QuantumInstructionSet
5
5
  from classiq.interface.generator.model.preferences.preferences import QuantumFormat
6
- from classiq.interface.hardware import Provider
7
6
 
8
7
  Code: TypeAlias = str
9
8
  CodeAndSyntax: TypeAlias = tuple[Code, QuantumInstructionSet]
@@ -14,14 +13,6 @@ INSTRUCTION_SET_TO_FORMAT: dict[QuantumInstructionSet, QuantumFormat] = {
14
13
  QuantumInstructionSet.IONQ: QuantumFormat.IONQ,
15
14
  QuantumInstructionSet.INTERNAL: QuantumFormat.EXECUTION_SERIALIZATION,
16
15
  }
17
- VENDOR_TO_INSTRUCTION_SET: dict[Provider, QuantumInstructionSet] = {
18
- Provider.CLASSIQ: QuantumInstructionSet.QASM,
19
- Provider.IONQ: QuantumInstructionSet.IONQ,
20
- Provider.AZURE_QUANTUM: QuantumInstructionSet.QSHARP,
21
- Provider.IBM_QUANTUM: QuantumInstructionSet.QASM,
22
- Provider.AMAZON_BRAKET: QuantumInstructionSet.QASM,
23
- }
24
- DEFAULT_INSTRUCTION_SET = QuantumInstructionSet.QASM
25
16
  _MAXIMUM_STRING_LENGTH = 250
26
17
 
27
18
 
@@ -2,6 +2,8 @@ EXPANDED_KEYWORD = "expanded__"
2
2
  CAPTURE_SUFFIX = "_captured__"
3
3
  LAMBDA_KEYWORD = "lambda__"
4
4
  INPLACE_ARITH_AUX_VAR_PREFIX = "_tmp"
5
+ THEN_KEYWORD = "then"
6
+ ELSE_KEYWORD = "else"
5
7
 
6
8
 
7
9
  def generate_original_function_name(name: str) -> str:
@@ -4,8 +4,6 @@ CLASSIQ_BUILTIN_CLASSICAL_FUNCTIONS = {
4
4
  "hypercube_entangler_graph",
5
5
  "grid_entangler_graph",
6
6
  "qft_const_adder_phase",
7
- "log_normal_finance_post_process",
8
- "gaussian_finance_post_process",
9
7
  "molecule_problem_to_hamiltonian",
10
8
  "fock_hamiltonian_problem_to_hamiltonian",
11
9
  "molecule_ground_state_solution_post_process",
@@ -1,14 +1,138 @@
1
1
  import itertools
2
2
 
3
+ from classiq.interface.generator.amplitude_loading import AmplitudeLoading
4
+ from classiq.interface.generator.arith.arithmetic import Arithmetic
5
+ from classiq.interface.generator.arith.binary_ops import (
6
+ Adder,
7
+ BitwiseAnd,
8
+ BitwiseOr,
9
+ BitwiseXor,
10
+ CyclicShift,
11
+ Equal,
12
+ GreaterEqual,
13
+ GreaterThan,
14
+ LessEqual,
15
+ LessThan,
16
+ LShift,
17
+ Modulo,
18
+ Multiplier,
19
+ NotEqual,
20
+ Power,
21
+ RShift,
22
+ Subtractor,
23
+ )
24
+ from classiq.interface.generator.arith.extremum_operations import Max, Min
25
+ from classiq.interface.generator.arith.logical_ops import LogicalAnd, LogicalOr
26
+ from classiq.interface.generator.arith.unary_ops import BitwiseInvert, Negation, Sign
27
+ from classiq.interface.generator.commuting_pauli_exponentiation import (
28
+ CommutingPauliExponentiation,
29
+ )
30
+ from classiq.interface.generator.copy import Copy
31
+ from classiq.interface.generator.entangler_params import (
32
+ GridEntangler,
33
+ HypercubeEntangler,
34
+ TwoDimensionalEntangler,
35
+ )
3
36
  from classiq.interface.generator.function_param_library import FunctionParamLibrary
4
- from classiq.interface.generator.function_param_list_without_self_reference import (
5
- function_param_library_without_self_reference,
37
+ from classiq.interface.generator.hadamard_transform import HadamardTransform
38
+ from classiq.interface.generator.hamiltonian_evolution.exponentiation import (
39
+ Exponentiation,
40
+ )
41
+ from classiq.interface.generator.hamiltonian_evolution.qdrift import QDrift
42
+ from classiq.interface.generator.hamiltonian_evolution.suzuki_trotter import (
43
+ SuzukiTrotter,
44
+ )
45
+ from classiq.interface.generator.hardware_efficient_ansatz import (
46
+ HardwareEfficientAnsatz,
47
+ )
48
+ from classiq.interface.generator.hartree_fock import HartreeFock
49
+ from classiq.interface.generator.hva import HVA
50
+ from classiq.interface.generator.identity import Identity
51
+ from classiq.interface.generator.linear_pauli_rotations import LinearPauliRotations
52
+ from classiq.interface.generator.mcu import Mcu
53
+ from classiq.interface.generator.mcx import Mcx
54
+ from classiq.interface.generator.qft import QFT
55
+ from classiq.interface.generator.qsvm import QSVMFeatureMap
56
+ from classiq.interface.generator.randomized_benchmarking import RandomizedBenchmarking
57
+ from classiq.interface.generator.reset import Reset
58
+ from classiq.interface.generator.standard_gates.standard_gates_param_list import (
59
+ standard_gate_function_param_library,
60
+ )
61
+ from classiq.interface.generator.standard_gates.u_gate import UGate
62
+ from classiq.interface.generator.state_preparation import (
63
+ BellStatePreparation,
64
+ ComputationalBasisStatePreparation,
65
+ ExponentialStatePreparation,
66
+ GHZStatePreparation,
67
+ StatePreparation,
68
+ UniformDistributionStatePreparation,
69
+ WStatePreparation,
6
70
  )
7
- from classiq.interface.generator.qpe import PhaseEstimation
71
+ from classiq.interface.generator.ucc import UCC
72
+ from classiq.interface.generator.unitary_gate import UnitaryGate
73
+ from classiq.interface.generator.user_defined_function_params import CustomFunction
8
74
 
9
75
  function_param_library: FunctionParamLibrary = FunctionParamLibrary(
10
76
  param_list=itertools.chain(
11
- function_param_library_without_self_reference.param_list,
12
- {PhaseEstimation},
77
+ {
78
+ StatePreparation,
79
+ ComputationalBasisStatePreparation,
80
+ UniformDistributionStatePreparation,
81
+ BellStatePreparation,
82
+ GHZStatePreparation,
83
+ WStatePreparation,
84
+ ExponentialStatePreparation,
85
+ QFT,
86
+ BitwiseAnd,
87
+ BitwiseOr,
88
+ BitwiseXor,
89
+ BitwiseInvert,
90
+ Adder,
91
+ Arithmetic,
92
+ Sign,
93
+ Equal,
94
+ NotEqual,
95
+ GreaterThan,
96
+ GreaterEqual,
97
+ LessThan,
98
+ LessEqual,
99
+ Negation,
100
+ LogicalAnd,
101
+ LogicalOr,
102
+ Subtractor,
103
+ RShift,
104
+ LShift,
105
+ CyclicShift,
106
+ Modulo,
107
+ TwoDimensionalEntangler,
108
+ HypercubeEntangler,
109
+ GridEntangler,
110
+ Mcx,
111
+ Mcu,
112
+ CustomFunction,
113
+ HardwareEfficientAnsatz,
114
+ UnitaryGate,
115
+ LinearPauliRotations,
116
+ Multiplier,
117
+ Power,
118
+ HartreeFock,
119
+ UCC,
120
+ Min,
121
+ Max,
122
+ Exponentiation,
123
+ CommutingPauliExponentiation,
124
+ SuzukiTrotter,
125
+ QDrift,
126
+ Identity,
127
+ RandomizedBenchmarking,
128
+ HVA,
129
+ UGate,
130
+ AmplitudeLoading,
131
+ QSVMFeatureMap,
132
+ HadamardTransform,
133
+ Copy,
134
+ Reset,
135
+ },
136
+ standard_gate_function_param_library.param_list,
13
137
  )
14
138
  )