classiq 0.38.0__py3-none-any.whl → 0.39.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 (137) hide show
  1. classiq/__init__.py +21 -22
  2. classiq/_internals/api_wrapper.py +13 -1
  3. classiq/_internals/client.py +12 -2
  4. classiq/analyzer/analyzer.py +3 -1
  5. classiq/applications/__init__.py +1 -8
  6. classiq/applications/chemistry/__init__.py +6 -0
  7. classiq/{applications_model_constructors → applications}/combinatorial_helpers/arithmetic/arithmetic_expression.py +1 -1
  8. classiq/{applications_model_constructors → applications}/combinatorial_helpers/combinatorial_problem_utils.py +26 -6
  9. classiq/{applications_model_constructors → applications}/combinatorial_helpers/encoding_mapping.py +1 -1
  10. classiq/{applications_model_constructors → applications}/combinatorial_helpers/encoding_utils.py +1 -1
  11. classiq/{applications_model_constructors → applications}/combinatorial_helpers/memory.py +2 -4
  12. classiq/{applications_model_constructors → applications}/combinatorial_helpers/optimization_model.py +6 -10
  13. classiq/{applications_model_constructors → applications}/combinatorial_helpers/pauli_helpers/pauli_utils.py +10 -0
  14. classiq/{applications_model_constructors → applications}/combinatorial_helpers/pyomo_utils.py +4 -2
  15. classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/encoding.py +3 -10
  16. classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/fixed_variables.py +4 -6
  17. classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/ising_converter.py +3 -5
  18. classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/penalty_support.py +3 -7
  19. classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/slack_variables.py +4 -6
  20. classiq/applications/combinatorial_optimization/__init__.py +9 -3
  21. classiq/{applications_model_constructors → applications/combinatorial_optimization}/combinatorial_optimization_model_constructor.py +7 -8
  22. classiq/applications/finance/__init__.py +3 -2
  23. classiq/{applications_model_constructors → applications/finance}/finance_model_constructor.py +24 -14
  24. classiq/applications/grover/__init__.py +11 -0
  25. classiq/applications/libraries/qmci_library.py +35 -0
  26. classiq/applications/qsvm/__init__.py +5 -1
  27. classiq/execution/all_hardware_devices.py +13 -0
  28. classiq/executor.py +2 -1
  29. classiq/interface/_version.py +1 -1
  30. classiq/interface/analyzer/result.py +1 -5
  31. classiq/interface/applications/qsvm.py +4 -2
  32. classiq/interface/ast_node.py +23 -0
  33. classiq/interface/combinatorial_optimization/examples/mht.py +8 -3
  34. classiq/interface/executor/execution_request.py +2 -37
  35. classiq/interface/executor/vqe_result.py +1 -1
  36. classiq/interface/generator/builtin_api_builder.py +0 -5
  37. classiq/interface/generator/constant.py +2 -3
  38. classiq/interface/generator/expressions/expression.py +2 -4
  39. classiq/interface/generator/expressions/qmod_qscalar_proxy.py +1 -1
  40. classiq/interface/generator/functions/__init__.py +2 -2
  41. classiq/interface/generator/functions/builtins/__init__.py +15 -0
  42. classiq/interface/generator/functions/builtins/core_library/__init__.py +14 -0
  43. classiq/interface/generator/functions/builtins/internal_operators.py +62 -0
  44. classiq/interface/generator/functions/{core_lib_declarations/quantum_functions/std_lib_functions.py → builtins/open_lib_functions.py} +109 -83
  45. classiq/interface/generator/functions/builtins/quantum_operators.py +37 -0
  46. classiq/interface/generator/functions/classical_type.py +2 -4
  47. classiq/interface/generator/functions/function_declaration.py +2 -2
  48. classiq/interface/generator/hartree_fock.py +10 -2
  49. classiq/interface/generator/model/classical_main_validator.py +1 -1
  50. classiq/interface/generator/model/model.py +1 -1
  51. classiq/interface/generator/quantum_function_call.py +1 -1
  52. classiq/interface/generator/types/struct_declaration.py +2 -4
  53. classiq/interface/model/call_synthesis_data.py +3 -3
  54. classiq/interface/model/classical_if.py +13 -0
  55. classiq/interface/model/classical_parameter_declaration.py +2 -3
  56. classiq/interface/model/control.py +16 -0
  57. classiq/interface/model/handle_binding.py +3 -2
  58. classiq/interface/model/invert.py +10 -0
  59. classiq/interface/model/model.py +2 -1
  60. classiq/interface/model/power.py +12 -0
  61. classiq/interface/model/quantum_function_call.py +9 -4
  62. classiq/interface/model/quantum_if_operation.py +3 -3
  63. classiq/interface/model/quantum_lambda_function.py +3 -9
  64. classiq/interface/model/quantum_statement.py +3 -2
  65. classiq/interface/model/quantum_type.py +2 -4
  66. classiq/interface/model/quantum_variable_declaration.py +2 -2
  67. classiq/interface/model/repeat.py +13 -0
  68. classiq/interface/model/resolvers/function_call_resolver.py +26 -0
  69. classiq/interface/model/statement_block.py +21 -4
  70. classiq/interface/model/validations/handles_validator.py +8 -12
  71. classiq/interface/model/within_apply_operation.py +4 -4
  72. classiq/interface/server/routes.py +0 -4
  73. classiq/qmod/builtins/classical_functions.py +9 -9
  74. classiq/qmod/builtins/functions.py +153 -226
  75. classiq/qmod/builtins/operations.py +160 -13
  76. classiq/qmod/native/pretty_printer.py +49 -20
  77. classiq/qmod/qmod_constant.py +26 -2
  78. classiq/qmod/qmod_parameter.py +2 -1
  79. classiq/qmod/qmod_variable.py +48 -15
  80. classiq/qmod/quantum_callable.py +1 -0
  81. classiq/qmod/quantum_expandable.py +6 -7
  82. classiq/qmod/quantum_function.py +4 -0
  83. classiq/qmod/symbolic.py +2 -2
  84. {classiq-0.38.0.dist-info → classiq-0.39.0.dist-info}/METADATA +1 -1
  85. {classiq-0.38.0.dist-info → classiq-0.39.0.dist-info}/RECORD +107 -124
  86. classiq/applications/benchmarking/__init__.py +0 -9
  87. classiq/applications/benchmarking/mirror_benchmarking.py +0 -70
  88. classiq/applications/numpy_utils.py +0 -37
  89. classiq/applications_model_constructors/__init__.py +0 -25
  90. classiq/applications_model_constructors/combinatorial_helpers/multiple_comp_basis_sp.py +0 -34
  91. classiq/applications_model_constructors/libraries/qmci_library.py +0 -107
  92. classiq/builtin_functions/__init__.py +0 -43
  93. classiq/builtin_functions/amplitude_loading.py +0 -3
  94. classiq/builtin_functions/binary_ops.py +0 -1
  95. classiq/builtin_functions/exponentiation.py +0 -5
  96. classiq/builtin_functions/qpe.py +0 -4
  97. classiq/builtin_functions/qsvm.py +0 -7
  98. classiq/builtin_functions/range_types.py +0 -5
  99. classiq/builtin_functions/standard_gates.py +0 -1
  100. classiq/builtin_functions/state_preparation.py +0 -6
  101. classiq/builtin_functions/suzuki_trotter.py +0 -3
  102. classiq/interface/generator/functions/core_lib_declarations/quantum_functions/__init__.py +0 -18
  103. classiq/interface/generator/functions/core_lib_declarations/quantum_operators.py +0 -95
  104. classiq/model/__init__.py +0 -14
  105. classiq/model/composite_function_generator.py +0 -33
  106. classiq/model/function_handler.py +0 -462
  107. classiq/model/logic_flow.py +0 -149
  108. classiq/model/logic_flow_change_handler.py +0 -71
  109. classiq/model/model.py +0 -229
  110. classiq/quantum_functions/__init__.py +0 -17
  111. classiq/quantum_functions/annotation_parser.py +0 -205
  112. classiq/quantum_functions/decorators.py +0 -22
  113. classiq/quantum_functions/function_library.py +0 -181
  114. classiq/quantum_functions/function_parser.py +0 -74
  115. classiq/quantum_functions/quantum_function.py +0 -236
  116. /classiq/{applications_model_constructors → applications/chemistry}/chemistry_model_constructor.py +0 -0
  117. /classiq/{applications_model_constructors → applications}/combinatorial_helpers/__init__.py +0 -0
  118. /classiq/{applications_model_constructors → applications}/combinatorial_helpers/allowed_constraints.py +0 -0
  119. /classiq/{applications_model_constructors → applications}/combinatorial_helpers/arithmetic/__init__.py +0 -0
  120. /classiq/{applications_model_constructors → applications}/combinatorial_helpers/arithmetic/isolation.py +0 -0
  121. /classiq/{applications_model_constructors → applications}/combinatorial_helpers/pauli_helpers/__init__.py +0 -0
  122. /classiq/{applications_model_constructors → applications}/combinatorial_helpers/pauli_helpers/pauli_sparsing.py +0 -0
  123. /classiq/{applications_model_constructors → applications}/combinatorial_helpers/py.typed +0 -0
  124. /classiq/{applications_model_constructors/combinatorial_helpers/transformations → applications/combinatorial_helpers/solvers}/__init__.py +0 -0
  125. /classiq/{applications_model_constructors → applications}/combinatorial_helpers/sympy_utils.py +0 -0
  126. /classiq/{applications_model_constructors/libraries → applications/combinatorial_helpers/transformations}/__init__.py +0 -0
  127. /classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/penalty.py +0 -0
  128. /classiq/{applications_model_constructors → applications}/combinatorial_helpers/transformations/sign_seperation.py +0 -0
  129. /classiq/{applications_model_constructors → applications/grover}/grover_model_constructor.py +0 -0
  130. /classiq/{interface/generator/functions/core_lib_declarations → applications/libraries}/__init__.py +0 -0
  131. /classiq/{applications_model_constructors → applications}/libraries/ampltitude_estimation_library.py +0 -0
  132. /classiq/{applications_model_constructors → applications/qsvm}/qsvm_model_constructor.py +0 -0
  133. /classiq/interface/generator/functions/{core_lib_declarations/quantum_functions → builtins/core_library}/atomic_quantum_functions.py +0 -0
  134. /classiq/interface/generator/functions/{core_lib_declarations/quantum_functions → builtins/core_library}/chemistry_functions.py +0 -0
  135. /classiq/interface/generator/functions/{core_lib_declarations/quantum_functions → builtins/core_library}/exponentiation_functions.py +0 -0
  136. /classiq/{quantum_register.py → interface/model/quantum_register.py} +0 -0
  137. {classiq-0.38.0.dist-info → classiq-0.39.0.dist-info}/WHEEL +0 -0
@@ -10,6 +10,143 @@ from classiq.qmod.quantum_callable import QCallable, QCallableList
10
10
  from .structs import *
11
11
 
12
12
 
13
+ @qfunc(external=True)
14
+ def permute(
15
+ functions: QCallableList,
16
+ ) -> None:
17
+ pass
18
+
19
+
20
+ @qfunc(external=True)
21
+ def apply(
22
+ operand: QCallable,
23
+ ) -> None:
24
+ pass
25
+
26
+
27
+ @qfunc(external=True)
28
+ def molecule_ucc(
29
+ molecule_problem: QParam[MoleculeProblem],
30
+ excitations: QParam[List[int]],
31
+ qbv: QArray[
32
+ QBit,
33
+ Literal[
34
+ "len(get_field(molecule_problem_to_hamiltonian(molecule_problem)[0], 'pauli'))"
35
+ ],
36
+ ],
37
+ ) -> None:
38
+ pass
39
+
40
+
41
+ @qfunc(external=True)
42
+ def molecule_hva(
43
+ molecule_problem: QParam[MoleculeProblem],
44
+ reps: QParam[int],
45
+ qbv: QArray[
46
+ QBit,
47
+ Literal[
48
+ "len(get_field(molecule_problem_to_hamiltonian(molecule_problem)[0], 'pauli'))"
49
+ ],
50
+ ],
51
+ ) -> None:
52
+ pass
53
+
54
+
55
+ @qfunc(external=True)
56
+ def molecule_hartree_fock(
57
+ molecule_problem: QParam[MoleculeProblem],
58
+ qbv: QArray[
59
+ QBit,
60
+ Literal[
61
+ "len(get_field(molecule_problem_to_hamiltonian(molecule_problem)[0], 'pauli'))"
62
+ ],
63
+ ],
64
+ ) -> None:
65
+ pass
66
+
67
+
68
+ @qfunc(external=True)
69
+ def fock_hamiltonian_ucc(
70
+ fock_hamiltonian_problem: QParam[FockHamiltonianProblem],
71
+ excitations: QParam[List[int]],
72
+ qbv: QArray[
73
+ QBit,
74
+ Literal[
75
+ "len(get_field(fock_hamiltonian_problem_to_hamiltonian(fock_hamiltonian_problem)[0], 'pauli'))"
76
+ ],
77
+ ],
78
+ ) -> None:
79
+ pass
80
+
81
+
82
+ @qfunc(external=True)
83
+ def fock_hamiltonian_hva(
84
+ fock_hamiltonian_problem: QParam[FockHamiltonianProblem],
85
+ reps: QParam[int],
86
+ qbv: QArray[
87
+ QBit,
88
+ Literal[
89
+ "len(get_field(fock_hamiltonian_problem_to_hamiltonian(fock_hamiltonian_problem)[0], 'pauli'))"
90
+ ],
91
+ ],
92
+ ) -> None:
93
+ pass
94
+
95
+
96
+ @qfunc(external=True)
97
+ def fock_hamiltonian_hartree_fock(
98
+ fock_hamiltonian_problem: QParam[FockHamiltonianProblem],
99
+ qbv: QArray[
100
+ QBit,
101
+ Literal[
102
+ "len(get_field(fock_hamiltonian_problem_to_hamiltonian(fock_hamiltonian_problem)[0], 'pauli'))"
103
+ ],
104
+ ],
105
+ ) -> None:
106
+ pass
107
+
108
+
109
+ @qfunc(external=True)
110
+ def log_normal_finance(
111
+ finance_model: QParam[LogNormalModel],
112
+ finance_function: QParam[FinanceFunction],
113
+ func_port: QArray[QBit, Literal["get_field(finance_model, 'num_qubits')"]],
114
+ obj_port: QBit,
115
+ ) -> None:
116
+ pass
117
+
118
+
119
+ @qfunc(external=True)
120
+ def gaussian_finance(
121
+ finance_model: QParam[GaussianModel],
122
+ finance_function: QParam[FinanceFunction],
123
+ func_port: QArray[
124
+ QBit,
125
+ Literal[
126
+ "get_field(finance_model, 'num_qubits') + len(get_field(finance_model, 'rhos')) + floor(log(sum(get_field(finance_model, 'loss')), 2)) + 1"
127
+ ],
128
+ ],
129
+ obj_port: QBit,
130
+ ) -> None:
131
+ pass
132
+
133
+
134
+ @qfunc(external=True)
135
+ def pauli_feature_map(
136
+ feature_map: QParam[QSVMFeatureMapPauli],
137
+ qbv: QArray[QBit, Literal["get_field(feature_map, 'feature_dimension')"]],
138
+ ) -> None:
139
+ pass
140
+
141
+
142
+ @qfunc(external=True)
143
+ def bloch_sphere_feature_map(
144
+ feature_dimension: QParam[int],
145
+ qbv: QArray[QBit, Literal["ceiling(feature_dimension/2)"]],
146
+ ) -> None:
147
+ pass
148
+
149
+
13
150
  @qfunc(external=True)
14
151
  def H(
15
152
  target: QBit,
@@ -402,15 +539,6 @@ def qpe(
402
539
  pass
403
540
 
404
541
 
405
- @qfunc(external=True)
406
- def standard_qpe(
407
- precision: QParam[int],
408
- unitary: QCallable,
409
- phase: QArray[QBit, Literal["precision"]],
410
- ) -> None:
411
- pass
412
-
413
-
414
542
  @qfunc(external=True)
415
543
  def single_pauli(
416
544
  slope: QParam[float],
@@ -435,12 +563,10 @@ def linear_pauli_rotations(
435
563
 
436
564
  @qfunc(external=True)
437
565
  def amplitude_estimation(
438
- num_phase_qubits: QParam[int],
439
- num_unitary_qubits: QParam[int],
440
- sp_op: QCallable[QParam[int], QArray[QBit, Literal["num_unitary_qubits"]]],
441
- oracle_op: QCallable[QParam[int], QArray[QBit, Literal["num_unitary_qubits"]]],
442
- phase_port: Output[QNum],
443
- unitary_port: Output[QArray[QBit, Literal["num_unitary_qubits"]]],
566
+ oracle: QCallable[QArray[QBit]],
567
+ space_transform: QCallable[QArray[QBit]],
568
+ phase: QNum,
569
+ packed_vars: QArray[QBit],
444
570
  ) -> None:
445
571
  pass
446
572
 
@@ -626,198 +752,19 @@ def switch(
626
752
  pass
627
753
 
628
754
 
629
- @qfunc(external=True)
630
- def repeat(
631
- count: QParam[int],
632
- iteration: QCallable[QParam[int]],
633
- ) -> None:
634
- pass
635
-
636
-
637
- @qfunc(external=True)
638
- def invert(
639
- operand: QCallable,
640
- ) -> None:
641
- pass
642
-
643
-
644
- @qfunc(external=True)
645
- def control(
646
- operand: QCallable,
647
- ctrl: QArray[QBit],
648
- ) -> None:
649
- pass
650
-
651
-
652
- @qfunc(external=True)
653
- def if_(
654
- condition: QParam[bool],
655
- then: QCallable,
656
- else_: QCallable,
657
- ) -> None:
658
- pass
659
-
660
-
661
- @qfunc(external=True)
662
- def permute(
663
- functions: QCallableList,
664
- ) -> None:
665
- pass
666
-
667
-
668
- @qfunc(external=True)
669
- def power(
670
- power: QParam[int],
671
- operand: QCallable,
672
- ) -> None:
673
- pass
674
-
675
-
676
- @qfunc(external=True)
677
- def apply(
678
- operand: QCallable,
679
- ) -> None:
680
- pass
681
-
682
-
683
- @qfunc(external=True)
684
- def compute(
685
- operand: QCallable,
686
- ) -> None:
687
- pass
688
-
689
-
690
- @qfunc(external=True)
691
- def uncompute(
692
- operand: QCallable,
693
- ) -> None:
694
- pass
695
-
696
-
697
- @qfunc(external=True)
698
- def molecule_ucc(
699
- molecule_problem: QParam[MoleculeProblem],
700
- excitations: QParam[List[int]],
701
- qbv: QArray[
702
- QBit,
703
- Literal[
704
- "len(get_field(molecule_problem_to_hamiltonian(molecule_problem)[0], 'pauli'))"
705
- ],
706
- ],
707
- ) -> None:
708
- pass
709
-
710
-
711
- @qfunc(external=True)
712
- def molecule_hva(
713
- molecule_problem: QParam[MoleculeProblem],
714
- reps: QParam[int],
715
- qbv: QArray[
716
- QBit,
717
- Literal[
718
- "len(get_field(molecule_problem_to_hamiltonian(molecule_problem)[0], 'pauli'))"
719
- ],
720
- ],
721
- ) -> None:
722
- pass
723
-
724
-
725
- @qfunc(external=True)
726
- def molecule_hartree_fock(
727
- molecule_problem: QParam[MoleculeProblem],
728
- qbv: QArray[
729
- QBit,
730
- Literal[
731
- "len(get_field(molecule_problem_to_hamiltonian(molecule_problem)[0], 'pauli'))"
732
- ],
733
- ],
734
- ) -> None:
735
- pass
736
-
737
-
738
- @qfunc(external=True)
739
- def fock_hamiltonian_ucc(
740
- fock_hamiltonian_problem: QParam[FockHamiltonianProblem],
741
- excitations: QParam[List[int]],
742
- qbv: QArray[
743
- QBit,
744
- Literal[
745
- "len(get_field(fock_hamiltonian_problem_to_hamiltonian(fock_hamiltonian_problem)[0], 'pauli'))"
746
- ],
747
- ],
748
- ) -> None:
749
- pass
750
-
751
-
752
- @qfunc(external=True)
753
- def fock_hamiltonian_hva(
754
- fock_hamiltonian_problem: QParam[FockHamiltonianProblem],
755
- reps: QParam[int],
756
- qbv: QArray[
757
- QBit,
758
- Literal[
759
- "len(get_field(fock_hamiltonian_problem_to_hamiltonian(fock_hamiltonian_problem)[0], 'pauli'))"
760
- ],
761
- ],
762
- ) -> None:
763
- pass
764
-
765
-
766
- @qfunc(external=True)
767
- def fock_hamiltonian_hartree_fock(
768
- fock_hamiltonian_problem: QParam[FockHamiltonianProblem],
769
- qbv: QArray[
770
- QBit,
771
- Literal[
772
- "len(get_field(fock_hamiltonian_problem_to_hamiltonian(fock_hamiltonian_problem)[0], 'pauli'))"
773
- ],
774
- ],
775
- ) -> None:
776
- pass
777
-
778
-
779
- @qfunc(external=True)
780
- def log_normal_finance(
781
- finance_model: QParam[LogNormalModel],
782
- finance_function: QParam[FinanceFunction],
783
- func_port: QArray[QBit, Literal["get_field(finance_model, 'num_qubits')"]],
784
- obj_port: QBit,
785
- ) -> None:
786
- pass
787
-
788
-
789
- @qfunc(external=True)
790
- def gaussian_finance(
791
- finance_model: QParam[GaussianModel],
792
- finance_function: QParam[FinanceFunction],
793
- func_port: QArray[
794
- QBit,
795
- Literal[
796
- "get_field(finance_model, 'num_qubits') + len(get_field(finance_model, 'rhos')) + floor(log(sum(get_field(finance_model, 'loss')), 2)) + 1"
797
- ],
798
- ],
799
- obj_port: QBit,
800
- ) -> None:
801
- pass
802
-
803
-
804
- @qfunc(external=True)
805
- def pauli_feature_map(
806
- feature_map: QParam[QSVMFeatureMapPauli],
807
- qbv: QArray[QBit, Literal["get_field(feature_map, 'feature_dimension')"]],
808
- ) -> None:
809
- pass
810
-
811
-
812
- @qfunc(external=True)
813
- def bloch_sphere_feature_map(
814
- feature_dimension: QParam[int],
815
- qbv: QArray[QBit, Literal["ceiling(feature_dimension/2)"]],
816
- ) -> None:
817
- pass
818
-
819
-
820
755
  __all__ = [
756
+ "permute",
757
+ "apply",
758
+ "molecule_ucc",
759
+ "molecule_hva",
760
+ "molecule_hartree_fock",
761
+ "fock_hamiltonian_ucc",
762
+ "fock_hamiltonian_hva",
763
+ "fock_hamiltonian_hartree_fock",
764
+ "log_normal_finance",
765
+ "gaussian_finance",
766
+ "pauli_feature_map",
767
+ "bloch_sphere_feature_map",
821
768
  "H",
822
769
  "X",
823
770
  "Y",
@@ -866,7 +813,6 @@ __all__ = [
866
813
  "qft",
867
814
  "qpe_flexible",
868
815
  "qpe",
869
- "standard_qpe",
870
816
  "single_pauli",
871
817
  "linear_pauli_rotations",
872
818
  "amplitude_estimation",
@@ -891,23 +837,4 @@ __all__ = [
891
837
  "inplace_prepare_int",
892
838
  "prepare_int",
893
839
  "switch",
894
- "repeat",
895
- "invert",
896
- "control",
897
- "if_",
898
- "permute",
899
- "power",
900
- "apply",
901
- "compute",
902
- "uncompute",
903
- "molecule_ucc",
904
- "molecule_hva",
905
- "molecule_hartree_fock",
906
- "fock_hamiltonian_ucc",
907
- "fock_hamiltonian_hva",
908
- "fock_hamiltonian_hartree_fock",
909
- "log_normal_finance",
910
- "gaussian_finance",
911
- "pauli_feature_map",
912
- "bloch_sphere_feature_map",
913
840
  ]
@@ -1,23 +1,38 @@
1
- from typing import Callable, List, Union
1
+ import inspect
2
+ from types import FrameType
3
+ from typing import Any, Callable, Final, List, Mapping, Union
2
4
 
3
5
  from classiq.interface.generator.expressions.expression import Expression
6
+ from classiq.interface.generator.functions.builtins.internal_operators import (
7
+ REPEAT_OPERATOR,
8
+ )
4
9
  from classiq.interface.model.bind_operation import BindOperation
10
+ from classiq.interface.model.classical_if import ClassicalIf
11
+ from classiq.interface.model.control import Control
5
12
  from classiq.interface.model.inplace_binary_operation import (
6
13
  BinaryOperation,
7
14
  InplaceBinaryOperation,
8
15
  )
9
- from classiq.interface.model.quantum_function_call import ArgValue
16
+ from classiq.interface.model.invert import Invert
17
+ from classiq.interface.model.power import Power
18
+ from classiq.interface.model.quantum_function_call import QuantumFunctionCall
10
19
  from classiq.interface.model.quantum_function_declaration import (
11
20
  QuantumOperandDeclaration,
12
21
  )
13
- from classiq.interface.model.quantum_if_operation import QuantumIfOperation
14
- from classiq.interface.model.within_apply_operation import WithinApplyOperation
15
-
16
- from classiq.qmod.qmod_variable import Input, Output, QNum, QVar
22
+ from classiq.interface.model.quantum_if_operation import QuantumIf
23
+ from classiq.interface.model.quantum_lambda_function import QuantumLambdaFunction
24
+ from classiq.interface.model.repeat import Repeat
25
+ from classiq.interface.model.statement_block import StatementBlock
26
+ from classiq.interface.model.within_apply_operation import WithinApply
27
+
28
+ from classiq.exceptions import ClassiqValueError
29
+ from classiq.qmod.qmod_variable import Input, Output, QArray, QBit, QNum, QVar
17
30
  from classiq.qmod.quantum_callable import QCallable
18
31
  from classiq.qmod.quantum_expandable import prepare_arg
19
32
  from classiq.qmod.symbolic_expr import SymbolicExpr
20
33
 
34
+ _MISSING_VALUE: Final[int] = -1
35
+
21
36
 
22
37
  def bind(
23
38
  source: Union[Input[QVar], List[Input[QVar]]],
@@ -36,14 +51,46 @@ def bind(
36
51
  )
37
52
 
38
53
 
54
+ def control(
55
+ operand: Union[QCallable, Callable[[], None]], ctrl: Union[QBit, QArray[QBit]]
56
+ ) -> None:
57
+ _validate_operand(operand)
58
+ assert QCallable.CURRENT_EXPANDABLE is not None
59
+ QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
60
+ Control(
61
+ control=ctrl.get_handle_binding(),
62
+ body=_operand_to_body(operand),
63
+ )
64
+ )
65
+
66
+
67
+ def if_(
68
+ condition: SymbolicExpr,
69
+ then: Union[QCallable, Callable[[], None]],
70
+ else_: Union[QCallable, Callable[[], None], int] = _MISSING_VALUE,
71
+ ) -> None:
72
+ _validate_operand(then)
73
+ if else_ != _MISSING_VALUE:
74
+ _validate_operand(else_)
75
+ assert QCallable.CURRENT_EXPANDABLE is not None
76
+ QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
77
+ ClassicalIf(
78
+ condition=Expression(expr=str(condition)),
79
+ then=_operand_to_body(then),
80
+ else_=_operand_to_body(else_) if else_ != _MISSING_VALUE else [], # type: ignore[arg-type]
81
+ )
82
+ )
83
+
84
+
39
85
  def quantum_if(
40
86
  condition: SymbolicExpr, then: Union[QCallable, Callable[[], None]]
41
87
  ) -> None:
88
+ _validate_operand(then)
42
89
  assert QCallable.CURRENT_EXPANDABLE is not None
43
90
  QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
44
- QuantumIfOperation(
91
+ QuantumIf(
45
92
  expression=Expression(expr=str(condition)),
46
- then=_to_operand(then),
93
+ then=_operand_to_body(then),
47
94
  )
48
95
  )
49
96
 
@@ -80,25 +127,125 @@ def within_apply(
80
127
  compute: Callable[[], None],
81
128
  action: Callable[[], None],
82
129
  ) -> None:
130
+ _validate_operand(compute)
131
+ _validate_operand(action)
132
+ assert QCallable.CURRENT_EXPANDABLE is not None
133
+ QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
134
+ WithinApply(
135
+ compute=_operand_to_body(compute),
136
+ action=_operand_to_body(action),
137
+ )
138
+ )
139
+
140
+
141
+ def repeat(count: Union[SymbolicExpr, int], iteration: Callable[[int], None]) -> None:
142
+ _validate_operand(iteration)
83
143
  assert QCallable.CURRENT_EXPANDABLE is not None
144
+ iteration_operand = prepare_arg(
145
+ REPEAT_OPERATOR.operand_declarations["iteration"], iteration
146
+ )
84
147
  QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
85
- WithinApplyOperation(
86
- compute=_to_operand(compute),
87
- action=_to_operand(action),
148
+ Repeat(
149
+ iter_var=inspect.getfullargspec(iteration).args[0],
150
+ count=Expression(expr=str(count)),
151
+ body=iteration_operand.body,
88
152
  )
89
153
  )
90
154
 
91
155
 
92
- def _to_operand(callable_: Union[QCallable, Callable[[], None]]) -> ArgValue:
93
- return prepare_arg(QuantumOperandDeclaration(name=""), callable_)
156
+ def power(
157
+ power: Union[SymbolicExpr, int],
158
+ operand: Union[QCallable, Callable[[], None]],
159
+ ) -> None:
160
+ _validate_operand(operand)
161
+ assert QCallable.CURRENT_EXPANDABLE is not None
162
+ QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
163
+ Power(power=Expression(expr=str(power)), body=_operand_to_body(operand))
164
+ )
165
+
166
+
167
+ def invert(
168
+ operand: Union[QCallable, Callable[[], None]],
169
+ ) -> None:
170
+ _validate_operand(operand)
171
+ assert QCallable.CURRENT_EXPANDABLE is not None
172
+ QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
173
+ Invert(body=_operand_to_body(operand))
174
+ )
175
+
176
+
177
+ def _validate_operand(operand: Any) -> None:
178
+ if operand is not None:
179
+ return
180
+ currentframe: FrameType = inspect.currentframe() # type: ignore[assignment]
181
+ operation_frame: FrameType = currentframe.f_back # type: ignore[assignment]
182
+ operation_frame_info: inspect.Traceback = inspect.getframeinfo(operation_frame)
183
+ operation_name: str = operation_frame_info.function
184
+
185
+ context = operation_frame_info.code_context
186
+ assert context is not None
187
+ operand_arg_name = context[0].split("_validate_operand(")[1].split(")")[0]
188
+
189
+ error_message = (
190
+ f"{operation_name} is missing required argument for {operand_arg_name}"
191
+ )
192
+ error_message += _get_operand_hint(
193
+ operation_name=operation_name,
194
+ operand_arg_name=operand_arg_name,
195
+ params=inspect.signature(operation_frame.f_globals[operation_name]).parameters,
196
+ )
197
+ raise ClassiqValueError(error_message)
198
+
199
+
200
+ def _get_operand_hint_args(
201
+ params: Mapping[str, inspect.Parameter], operand_arg_name: str, operand_value: str
202
+ ) -> str:
203
+ return ", ".join(
204
+ [
205
+ (
206
+ f"{param.name}={operand_value}"
207
+ if param.name == operand_arg_name
208
+ else f"{param.name}=..."
209
+ )
210
+ for param in params.values()
211
+ ]
212
+ )
213
+
214
+
215
+ def _get_operand_hint(
216
+ operation_name: str, operand_arg_name: str, params: Mapping[str, inspect.Parameter]
217
+ ) -> str:
218
+ return (
219
+ f"\nHint: To create an operand, do not call quantum gates directly "
220
+ f"`{operation_name}({_get_operand_hint_args(params, operand_arg_name, 'H(q)')})`. "
221
+ f"Instead, use a lambda function "
222
+ f"`{operation_name}({_get_operand_hint_args(params, operand_arg_name, 'lambda: H(q)')})` "
223
+ f"or a quantum function "
224
+ f"`{operation_name}({_get_operand_hint_args(params, operand_arg_name, 'my_func')})`"
225
+ )
226
+
227
+
228
+ def _operand_to_body(callable_: Union[QCallable, Callable[[], None]]) -> StatementBlock:
229
+ to_operand = prepare_arg(QuantumOperandDeclaration(name=""), callable_)
230
+ if isinstance(to_operand, str):
231
+ return [QuantumFunctionCall(function=to_operand)]
232
+ elif isinstance(to_operand, QuantumLambdaFunction):
233
+ return to_operand.body
234
+ else:
235
+ raise ValueError(f"Unexpected operand type: {type(to_operand)}")
94
236
 
95
237
 
96
238
  __all__ = [
97
239
  "bind",
240
+ "control",
241
+ "invert",
242
+ "if_",
98
243
  "quantum_if",
99
244
  "inplace_add",
100
245
  "inplace_xor",
246
+ "power",
101
247
  "within_apply",
248
+ "repeat",
102
249
  ]
103
250
 
104
251