classiq 0.37.1__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.
- classiq/__init__.py +23 -24
- classiq/_analyzer_extras/_ipywidgets_async_extension.py +1 -1
- classiq/_analyzer_extras/interactive_hardware.py +3 -3
- classiq/_internals/api_wrapper.py +37 -17
- classiq/_internals/async_utils.py +1 -74
- classiq/_internals/authentication/device.py +9 -4
- classiq/_internals/authentication/password_manager.py +25 -10
- classiq/_internals/authentication/token_manager.py +2 -2
- classiq/_internals/client.py +24 -6
- classiq/_internals/jobs.py +10 -7
- classiq/analyzer/analyzer.py +29 -29
- classiq/analyzer/analyzer_utilities.py +5 -5
- classiq/analyzer/rb.py +4 -5
- classiq/analyzer/show_interactive_hack.py +6 -6
- classiq/applications/__init__.py +1 -8
- classiq/applications/chemistry/__init__.py +6 -0
- classiq/{applications_model_constructors → applications/chemistry}/chemistry_model_constructor.py +9 -16
- classiq/applications/combinatorial_helpers/allowed_constraints.py +20 -0
- classiq/applications/combinatorial_helpers/arithmetic/arithmetic_expression.py +35 -0
- classiq/applications/combinatorial_helpers/arithmetic/isolation.py +42 -0
- classiq/applications/combinatorial_helpers/combinatorial_problem_utils.py +150 -0
- classiq/applications/combinatorial_helpers/encoding_mapping.py +107 -0
- classiq/applications/combinatorial_helpers/encoding_utils.py +122 -0
- classiq/applications/combinatorial_helpers/memory.py +77 -0
- classiq/applications/combinatorial_helpers/optimization_model.py +162 -0
- classiq/applications/combinatorial_helpers/pauli_helpers/pauli_sparsing.py +31 -0
- classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +75 -0
- classiq/applications/combinatorial_helpers/py.typed +0 -0
- classiq/applications/combinatorial_helpers/pyomo_utils.py +245 -0
- classiq/applications/combinatorial_helpers/solvers/__init__.py +0 -0
- classiq/applications/combinatorial_helpers/sympy_utils.py +22 -0
- classiq/applications/combinatorial_helpers/transformations/__init__.py +0 -0
- classiq/applications/combinatorial_helpers/transformations/encoding.py +187 -0
- classiq/applications/combinatorial_helpers/transformations/fixed_variables.py +142 -0
- classiq/applications/combinatorial_helpers/transformations/ising_converter.py +122 -0
- classiq/applications/combinatorial_helpers/transformations/penalty.py +32 -0
- classiq/applications/combinatorial_helpers/transformations/penalty_support.py +37 -0
- classiq/applications/combinatorial_helpers/transformations/sign_seperation.py +75 -0
- classiq/applications/combinatorial_helpers/transformations/slack_variables.py +88 -0
- classiq/applications/combinatorial_optimization/__init__.py +13 -2
- classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +134 -0
- classiq/applications/finance/__init__.py +3 -2
- classiq/{applications_model_constructors → applications/finance}/finance_model_constructor.py +27 -30
- classiq/applications/grover/__init__.py +11 -0
- classiq/{applications_model_constructors → applications/grover}/grover_model_constructor.py +20 -91
- classiq/applications/libraries/__init__.py +0 -0
- classiq/applications/libraries/qmci_library.py +35 -0
- classiq/applications/qnn/circuit_utils.py +2 -2
- classiq/applications/qnn/gradients/quantum_gradient.py +2 -2
- classiq/applications/qnn/types.py +2 -2
- classiq/applications/qsvm/__init__.py +5 -1
- classiq/applications/qsvm/qsvm.py +4 -7
- classiq/applications/qsvm/qsvm_data_generation.py +2 -5
- classiq/exceptions.py +43 -1
- classiq/execution/all_hardware_devices.py +13 -0
- classiq/executor.py +12 -10
- classiq/interface/_version.py +1 -1
- classiq/interface/analyzer/analysis_params.py +6 -3
- classiq/interface/analyzer/result.py +12 -8
- classiq/interface/applications/qsvm.py +17 -3
- classiq/interface/ast_node.py +23 -0
- classiq/interface/backend/backend_preferences.py +4 -2
- classiq/interface/backend/pydantic_backend.py +3 -1
- classiq/interface/backend/quantum_backend_providers.py +1 -0
- classiq/interface/chemistry/fermionic_operator.py +15 -13
- classiq/interface/chemistry/ground_state_problem.py +18 -3
- classiq/interface/chemistry/molecule.py +8 -6
- classiq/interface/chemistry/operator.py +20 -14
- classiq/interface/combinatorial_optimization/examples/ascending_sequence.py +1 -1
- classiq/interface/combinatorial_optimization/examples/greater_than_ilp.py +1 -1
- classiq/interface/combinatorial_optimization/examples/ilp.py +2 -1
- classiq/interface/combinatorial_optimization/examples/integer_portfolio_optimization.py +2 -2
- classiq/interface/combinatorial_optimization/examples/mds.py +2 -1
- classiq/interface/combinatorial_optimization/examples/mht.py +8 -3
- classiq/interface/combinatorial_optimization/examples/mis.py +4 -1
- classiq/interface/combinatorial_optimization/examples/mvc.py +2 -1
- classiq/interface/combinatorial_optimization/examples/set_cover.py +2 -1
- classiq/interface/combinatorial_optimization/examples/tsp.py +4 -3
- classiq/interface/combinatorial_optimization/examples/tsp_digraph.py +6 -2
- classiq/interface/combinatorial_optimization/mht_qaoa_input.py +9 -3
- classiq/interface/executor/aws_execution_cost.py +4 -3
- classiq/interface/executor/estimation.py +2 -2
- classiq/interface/executor/execution_preferences.py +5 -34
- classiq/interface/executor/execution_request.py +15 -48
- classiq/interface/executor/optimizer_preferences.py +22 -13
- classiq/interface/executor/{quantum_program.py → quantum_code.py} +21 -15
- classiq/interface/executor/quantum_instruction_set.py +2 -1
- classiq/interface/executor/register_initialization.py +1 -3
- classiq/interface/executor/result.py +41 -10
- classiq/interface/executor/vqe_result.py +2 -2
- classiq/interface/finance/function_input.py +17 -4
- classiq/interface/finance/gaussian_model_input.py +3 -1
- classiq/interface/finance/log_normal_model_input.py +3 -1
- classiq/interface/finance/model_input.py +2 -0
- classiq/interface/generator/amplitude_loading.py +6 -3
- classiq/interface/generator/application_apis/__init__.py +1 -0
- classiq/interface/generator/application_apis/arithmetic_declarations.py +14 -0
- classiq/interface/generator/arith/argument_utils.py +14 -4
- classiq/interface/generator/arith/arithmetic.py +3 -1
- classiq/interface/generator/arith/arithmetic_arg_type_validator.py +12 -13
- classiq/interface/generator/arith/arithmetic_expression_abc.py +4 -1
- classiq/interface/generator/arith/arithmetic_expression_parser.py +8 -2
- classiq/interface/generator/arith/arithmetic_expression_validator.py +16 -2
- classiq/interface/generator/arith/arithmetic_operations.py +5 -10
- classiq/interface/generator/arith/ast_node_rewrite.py +1 -1
- classiq/interface/generator/arith/binary_ops.py +202 -54
- classiq/interface/generator/arith/extremum_operations.py +5 -3
- classiq/interface/generator/arith/logical_ops.py +4 -2
- classiq/interface/generator/arith/machine_precision.py +3 -0
- classiq/interface/generator/arith/number_utils.py +34 -44
- classiq/interface/generator/arith/register_user_input.py +21 -1
- classiq/interface/generator/arith/unary_ops.py +16 -25
- classiq/interface/generator/builtin_api_builder.py +0 -5
- classiq/interface/generator/chemistry_function_params.py +4 -4
- classiq/interface/generator/commuting_pauli_exponentiation.py +3 -1
- classiq/interface/generator/compiler_keywords.py +4 -0
- classiq/interface/generator/complex_type.py +3 -10
- classiq/interface/generator/constant.py +2 -3
- classiq/interface/generator/control_state.py +5 -3
- classiq/interface/generator/credit_risk_example/linear_gci.py +10 -3
- classiq/interface/generator/credit_risk_example/weighted_adder.py +14 -4
- classiq/interface/generator/expressions/atomic_expression_functions.py +5 -3
- classiq/interface/generator/expressions/evaluated_expression.py +18 -4
- classiq/interface/generator/expressions/expression.py +3 -5
- classiq/interface/generator/expressions/qmod_qscalar_proxy.py +33 -0
- classiq/interface/generator/expressions/sympy_supported_expressions.py +2 -1
- classiq/interface/generator/finance.py +1 -1
- classiq/interface/generator/function_params.py +7 -6
- classiq/interface/generator/functions/__init__.py +2 -2
- classiq/interface/generator/functions/builtins/__init__.py +15 -0
- classiq/interface/generator/functions/builtins/core_library/__init__.py +14 -0
- classiq/interface/generator/functions/builtins/core_library/chemistry_functions.py +0 -0
- classiq/interface/generator/functions/builtins/internal_operators.py +62 -0
- classiq/interface/generator/functions/{core_lib_declarations/quantum_functions/std_lib_functions.py → builtins/open_lib_functions.py} +612 -219
- classiq/interface/generator/functions/builtins/quantum_operators.py +37 -0
- classiq/interface/generator/functions/classical_type.py +2 -4
- classiq/interface/generator/functions/foreign_function_definition.py +12 -4
- classiq/interface/generator/functions/function_declaration.py +2 -2
- classiq/interface/generator/functions/function_implementation.py +8 -4
- classiq/interface/generator/functions/native_function_definition.py +4 -2
- classiq/interface/generator/functions/register.py +4 -2
- classiq/interface/generator/functions/register_mapping_data.py +14 -10
- classiq/interface/generator/generated_circuit_data.py +2 -2
- classiq/interface/generator/grover_operator.py +5 -3
- classiq/interface/generator/hamiltonian_evolution/suzuki_trotter.py +5 -1
- classiq/interface/generator/hardware/hardware_data.py +6 -4
- classiq/interface/generator/hardware_efficient_ansatz.py +25 -8
- classiq/interface/generator/hartree_fock.py +13 -3
- classiq/interface/generator/linear_pauli_rotations.py +3 -1
- classiq/interface/generator/mcu.py +5 -3
- classiq/interface/generator/mcx.py +7 -5
- classiq/interface/generator/model/classical_main_validator.py +1 -1
- classiq/interface/generator/model/constraints.py +2 -1
- classiq/interface/generator/model/model.py +12 -20
- classiq/interface/generator/model/preferences/preferences.py +4 -3
- classiq/interface/generator/oracles/custom_oracle.py +4 -2
- classiq/interface/generator/oracles/oracle_abc.py +2 -2
- classiq/interface/generator/qpe.py +6 -4
- classiq/interface/generator/qsvm.py +5 -8
- classiq/interface/generator/quantum_function_call.py +21 -16
- classiq/interface/generator/{generated_circuit.py → quantum_program.py} +10 -14
- classiq/interface/generator/range_types.py +3 -1
- classiq/interface/generator/slice_parsing_utils.py +8 -3
- classiq/interface/generator/standard_gates/controlled_standard_gates.py +4 -2
- classiq/interface/generator/state_preparation/metrics.py +2 -1
- classiq/interface/generator/state_preparation/state_preparation.py +7 -5
- classiq/interface/generator/state_propagator.py +16 -5
- classiq/interface/generator/types/builtin_struct_declarations/__init__.py +0 -1
- classiq/interface/generator/types/struct_declaration.py +10 -7
- classiq/interface/generator/ucc.py +6 -4
- classiq/interface/generator/unitary_gate.py +7 -3
- classiq/interface/generator/validations/flow_graph.py +6 -4
- classiq/interface/generator/validations/validator_functions.py +6 -4
- classiq/interface/hardware.py +2 -2
- classiq/interface/helpers/custom_encoders.py +3 -0
- classiq/interface/helpers/pydantic_model_helpers.py +0 -6
- classiq/interface/helpers/validation_helpers.py +1 -1
- classiq/interface/helpers/versioned_model.py +4 -1
- classiq/interface/ide/show.py +2 -2
- classiq/interface/jobs.py +72 -3
- classiq/interface/model/bind_operation.py +18 -11
- classiq/interface/model/call_synthesis_data.py +68 -0
- classiq/interface/model/classical_if.py +13 -0
- classiq/interface/model/classical_parameter_declaration.py +2 -3
- classiq/interface/model/control.py +16 -0
- classiq/interface/model/handle_binding.py +3 -2
- classiq/interface/model/inplace_binary_operation.py +2 -2
- classiq/interface/model/invert.py +10 -0
- classiq/interface/model/model.py +29 -22
- classiq/interface/model/native_function_definition.py +3 -5
- classiq/interface/model/power.py +12 -0
- classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +9 -4
- classiq/interface/model/quantum_expressions/control_state.py +2 -2
- classiq/interface/model/quantum_function_call.py +33 -142
- classiq/interface/model/quantum_function_declaration.py +8 -0
- classiq/interface/model/quantum_if_operation.py +4 -5
- classiq/interface/model/quantum_lambda_function.py +58 -0
- classiq/{quantum_register.py → interface/model/quantum_register.py} +17 -9
- classiq/interface/model/quantum_statement.py +3 -2
- classiq/interface/model/quantum_type.py +58 -59
- classiq/interface/model/quantum_variable_declaration.py +3 -3
- classiq/interface/model/repeat.py +13 -0
- classiq/interface/model/resolvers/function_call_resolver.py +26 -0
- classiq/interface/model/statement_block.py +49 -0
- classiq/interface/model/validations/handles_validator.py +16 -18
- classiq/interface/model/within_apply_operation.py +11 -0
- classiq/interface/pyomo_extension/pyomo_sympy_bimap.py +4 -1
- classiq/interface/server/routes.py +5 -4
- classiq/qmod/__init__.py +13 -6
- classiq/qmod/builtins/classical_execution_primitives.py +27 -36
- classiq/qmod/builtins/classical_functions.py +22 -12
- classiq/qmod/builtins/functions.py +272 -328
- classiq/qmod/builtins/operations.py +171 -35
- classiq/qmod/builtins/structs.py +15 -15
- classiq/qmod/cfunc.py +42 -0
- classiq/qmod/classical_function.py +6 -14
- classiq/qmod/declaration_inferrer.py +12 -21
- classiq/qmod/expression_query.py +23 -0
- classiq/qmod/model_state_container.py +2 -0
- classiq/qmod/native/__init__.py +0 -0
- classiq/qmod/native/expression_to_qmod.py +189 -0
- classiq/qmod/native/pretty_printer.py +340 -0
- classiq/qmod/qfunc.py +27 -0
- classiq/qmod/qmod_constant.py +100 -0
- classiq/qmod/qmod_parameter.py +36 -13
- classiq/qmod/qmod_struct.py +3 -3
- classiq/qmod/qmod_variable.py +148 -31
- classiq/qmod/quantum_callable.py +1 -0
- classiq/qmod/quantum_expandable.py +18 -19
- classiq/qmod/quantum_function.py +41 -8
- classiq/qmod/symbolic.py +48 -5
- classiq/qmod/symbolic_expr.py +9 -0
- classiq/qmod/utilities.py +13 -0
- classiq/qmod/write_qmod.py +39 -0
- {classiq-0.37.1.dist-info → classiq-0.39.0.dist-info}/METADATA +2 -1
- {classiq-0.37.1.dist-info → classiq-0.39.0.dist-info}/RECORD +244 -225
- {classiq-0.37.1.dist-info → classiq-0.39.0.dist-info}/WHEEL +1 -1
- classiq/applications/benchmarking/__init__.py +0 -9
- classiq/applications/benchmarking/mirror_benchmarking.py +0 -67
- classiq/applications/numpy_utils.py +0 -37
- classiq/applications_model_constructors/__init__.py +0 -17
- classiq/applications_model_constructors/combinatorial_optimization_model_constructor.py +0 -178
- classiq/applications_model_constructors/libraries/qmci_library.py +0 -109
- classiq/builtin_functions/__init__.py +0 -43
- classiq/builtin_functions/amplitude_loading.py +0 -3
- classiq/builtin_functions/binary_ops.py +0 -1
- classiq/builtin_functions/exponentiation.py +0 -5
- classiq/builtin_functions/qpe.py +0 -4
- classiq/builtin_functions/qsvm.py +0 -7
- classiq/builtin_functions/range_types.py +0 -5
- classiq/builtin_functions/standard_gates.py +0 -1
- classiq/builtin_functions/state_preparation.py +0 -6
- classiq/builtin_functions/suzuki_trotter.py +0 -3
- classiq/interface/generator/expressions/qmod_qnum_proxy.py +0 -22
- classiq/interface/generator/functions/core_lib_declarations/quantum_functions/__init__.py +0 -18
- classiq/interface/generator/functions/core_lib_declarations/quantum_operators.py +0 -169
- classiq/interface/generator/types/builtin_struct_declarations/qaoa_declarations.py +0 -23
- classiq/interface/generator/types/combinatorial_problem.py +0 -26
- classiq/interface/model/numeric_reinterpretation.py +0 -25
- classiq/interface/model/operator_synthesis_data.py +0 -48
- classiq/model/__init__.py +0 -14
- classiq/model/composite_function_generator.py +0 -33
- classiq/model/function_handler.py +0 -466
- classiq/model/function_handler.pyi +0 -152
- classiq/model/logic_flow.py +0 -149
- classiq/model/logic_flow_change_handler.py +0 -71
- classiq/model/model.py +0 -246
- classiq/quantum_functions/__init__.py +0 -17
- classiq/quantum_functions/annotation_parser.py +0 -207
- classiq/quantum_functions/decorators.py +0 -22
- classiq/quantum_functions/function_library.py +0 -181
- classiq/quantum_functions/function_parser.py +0 -74
- classiq/quantum_functions/quantum_function.py +0 -236
- /classiq/{applications_model_constructors/libraries → applications/combinatorial_helpers}/__init__.py +0 -0
- /classiq/{interface/generator/functions/core_lib_declarations → applications/combinatorial_helpers/arithmetic}/__init__.py +0 -0
- /classiq/{interface/generator/functions/core_lib_declarations/quantum_functions/chemistry_functions.py → applications/combinatorial_helpers/pauli_helpers/__init__.py} +0 -0
- /classiq/{applications_model_constructors → applications}/libraries/ampltitude_estimation_library.py +0 -0
- /classiq/{applications_model_constructors → applications/qsvm}/qsvm_model_constructor.py +0 -0
- /classiq/interface/generator/functions/{core_lib_declarations/quantum_functions → builtins/core_library}/atomic_quantum_functions.py +0 -0
- /classiq/interface/generator/functions/{core_lib_declarations/quantum_functions → builtins/core_library}/exponentiation_functions.py +0 -0
@@ -1,67 +1,96 @@
|
|
1
|
-
|
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
|
4
|
-
from classiq.interface.generator.functions.
|
5
|
-
|
6
|
+
from classiq.interface.generator.functions.builtins.internal_operators import (
|
7
|
+
REPEAT_OPERATOR,
|
6
8
|
)
|
7
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
|
8
12
|
from classiq.interface.model.inplace_binary_operation import (
|
9
13
|
BinaryOperation,
|
10
14
|
InplaceBinaryOperation,
|
11
15
|
)
|
12
|
-
from classiq.interface.model.
|
13
|
-
|
14
|
-
|
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
|
15
19
|
from classiq.interface.model.quantum_function_declaration import (
|
16
20
|
QuantumOperandDeclaration,
|
17
21
|
)
|
18
|
-
from classiq.interface.model.quantum_if_operation import
|
19
|
-
|
20
|
-
from classiq.
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
from classiq.qmod.
|
26
|
-
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
|
27
30
|
from classiq.qmod.quantum_callable import QCallable
|
28
31
|
from classiq.qmod.quantum_expandable import prepare_arg
|
29
32
|
from classiq.qmod.symbolic_expr import SymbolicExpr
|
30
33
|
|
34
|
+
_MISSING_VALUE: Final[int] = -1
|
35
|
+
|
31
36
|
|
32
|
-
def bind(
|
37
|
+
def bind(
|
38
|
+
source: Union[Input[QVar], List[Input[QVar]]],
|
39
|
+
destination: Union[Output[QVar], List[Output[QVar]]],
|
40
|
+
) -> None:
|
33
41
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
42
|
+
if not isinstance(source, list):
|
43
|
+
source = [source]
|
44
|
+
if not isinstance(destination, list):
|
45
|
+
destination = [destination]
|
34
46
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
35
47
|
BindOperation(
|
36
|
-
|
37
|
-
|
48
|
+
in_handles=[src_var.get_handle_binding() for src_var in source],
|
49
|
+
out_handles=[dst_var.get_handle_binding() for dst_var in destination],
|
38
50
|
)
|
39
51
|
)
|
40
52
|
|
41
53
|
|
42
|
-
def
|
43
|
-
|
54
|
+
def control(
|
55
|
+
operand: Union[QCallable, Callable[[], None]], ctrl: Union[QBit, QArray[QBit]]
|
44
56
|
) -> None:
|
57
|
+
_validate_operand(operand)
|
45
58
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
46
59
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
47
|
-
|
48
|
-
|
49
|
-
|
60
|
+
Control(
|
61
|
+
control=ctrl.get_handle_binding(),
|
62
|
+
body=_operand_to_body(operand),
|
50
63
|
)
|
51
64
|
)
|
52
65
|
|
53
66
|
|
54
|
-
def
|
55
|
-
|
56
|
-
|
57
|
-
|
67
|
+
def if_(
|
68
|
+
condition: SymbolicExpr,
|
69
|
+
then: Union[QCallable, Callable[[], None]],
|
70
|
+
else_: Union[QCallable, Callable[[], None], int] = _MISSING_VALUE,
|
58
71
|
) -> None:
|
72
|
+
_validate_operand(then)
|
73
|
+
if else_ != _MISSING_VALUE:
|
74
|
+
_validate_operand(else_)
|
59
75
|
assert QCallable.CURRENT_EXPANDABLE is not None
|
60
76
|
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
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
|
+
|
85
|
+
def quantum_if(
|
86
|
+
condition: SymbolicExpr, then: Union[QCallable, Callable[[], None]]
|
87
|
+
) -> None:
|
88
|
+
_validate_operand(then)
|
89
|
+
assert QCallable.CURRENT_EXPANDABLE is not None
|
90
|
+
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
91
|
+
QuantumIf(
|
92
|
+
expression=Expression(expr=str(condition)),
|
93
|
+
then=_operand_to_body(then),
|
65
94
|
)
|
66
95
|
)
|
67
96
|
|
@@ -98,18 +127,125 @@ def within_apply(
|
|
98
127
|
compute: Callable[[], None],
|
99
128
|
action: Callable[[], None],
|
100
129
|
) -> None:
|
101
|
-
|
102
|
-
|
103
|
-
|
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)
|
143
|
+
assert QCallable.CURRENT_EXPANDABLE is not None
|
144
|
+
iteration_operand = prepare_arg(
|
145
|
+
REPEAT_OPERATOR.operand_declarations["iteration"], iteration
|
146
|
+
)
|
147
|
+
QCallable.CURRENT_EXPANDABLE.append_statement_to_body(
|
148
|
+
Repeat(
|
149
|
+
iter_var=inspect.getfullargspec(iteration).args[0],
|
150
|
+
count=Expression(expr=str(count)),
|
151
|
+
body=iteration_operand.body,
|
152
|
+
)
|
153
|
+
)
|
154
|
+
|
155
|
+
|
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)}")
|
104
236
|
|
105
237
|
|
106
238
|
__all__ = [
|
107
239
|
"bind",
|
240
|
+
"control",
|
241
|
+
"invert",
|
242
|
+
"if_",
|
108
243
|
"quantum_if",
|
109
|
-
"reinterpret_num",
|
110
244
|
"inplace_add",
|
111
245
|
"inplace_xor",
|
246
|
+
"power",
|
112
247
|
"within_apply",
|
248
|
+
"repeat",
|
113
249
|
]
|
114
250
|
|
115
251
|
|
classiq/qmod/builtins/structs.py
CHANGED
@@ -2,16 +2,16 @@
|
|
2
2
|
|
3
3
|
from typing import List
|
4
4
|
|
5
|
-
from classiq.qmod.qmod_struct import
|
5
|
+
from classiq.qmod.qmod_struct import struct
|
6
6
|
|
7
7
|
|
8
|
-
@
|
8
|
+
@struct
|
9
9
|
class PauliTerm:
|
10
10
|
pauli: List[int]
|
11
11
|
coefficient: float
|
12
12
|
|
13
13
|
|
14
|
-
@
|
14
|
+
@struct
|
15
15
|
class MoleculeProblem:
|
16
16
|
mapping: int
|
17
17
|
z2_symmetries: bool
|
@@ -20,27 +20,27 @@ class MoleculeProblem:
|
|
20
20
|
remove_orbitals: List[int]
|
21
21
|
|
22
22
|
|
23
|
-
@
|
23
|
+
@struct
|
24
24
|
class Molecule:
|
25
25
|
atoms: List["ChemistryAtom"]
|
26
26
|
spin: int
|
27
27
|
charge: int
|
28
28
|
|
29
29
|
|
30
|
-
@
|
30
|
+
@struct
|
31
31
|
class ChemistryAtom:
|
32
32
|
element: int
|
33
33
|
position: "Position"
|
34
34
|
|
35
35
|
|
36
|
-
@
|
36
|
+
@struct
|
37
37
|
class Position:
|
38
38
|
x: float
|
39
39
|
y: float
|
40
40
|
z: float
|
41
41
|
|
42
42
|
|
43
|
-
@
|
43
|
+
@struct
|
44
44
|
class FockHamiltonianProblem:
|
45
45
|
mapping: int
|
46
46
|
z2_symmetries: bool
|
@@ -48,19 +48,19 @@ class FockHamiltonianProblem:
|
|
48
48
|
num_particles: List[int]
|
49
49
|
|
50
50
|
|
51
|
-
@
|
51
|
+
@struct
|
52
52
|
class LadderTerm:
|
53
53
|
coefficient: float
|
54
54
|
ops: List["LadderOp"]
|
55
55
|
|
56
56
|
|
57
|
-
@
|
57
|
+
@struct
|
58
58
|
class LadderOp:
|
59
59
|
op: int
|
60
60
|
index: int
|
61
61
|
|
62
62
|
|
63
|
-
@
|
63
|
+
@struct
|
64
64
|
class CombinatorialOptimizationSolution:
|
65
65
|
probability: float
|
66
66
|
cost: float
|
@@ -68,7 +68,7 @@ class CombinatorialOptimizationSolution:
|
|
68
68
|
count: int
|
69
69
|
|
70
70
|
|
71
|
-
@
|
71
|
+
@struct
|
72
72
|
class GaussianModel:
|
73
73
|
num_qubits: int
|
74
74
|
normal_max_value: float
|
@@ -78,14 +78,14 @@ class GaussianModel:
|
|
78
78
|
min_loss: int
|
79
79
|
|
80
80
|
|
81
|
-
@
|
81
|
+
@struct
|
82
82
|
class LogNormalModel:
|
83
83
|
num_qubits: int
|
84
84
|
mu: float
|
85
85
|
sigma: float
|
86
86
|
|
87
87
|
|
88
|
-
@
|
88
|
+
@struct
|
89
89
|
class FinanceFunction:
|
90
90
|
f: int
|
91
91
|
threshold: float
|
@@ -95,13 +95,13 @@ class FinanceFunction:
|
|
95
95
|
tail_probability: float
|
96
96
|
|
97
97
|
|
98
|
-
@
|
98
|
+
@struct
|
99
99
|
class QsvmResult:
|
100
100
|
test_score: float
|
101
101
|
predicted_labels: List[float]
|
102
102
|
|
103
103
|
|
104
|
-
@
|
104
|
+
@struct
|
105
105
|
class QSVMFeatureMapPauli:
|
106
106
|
feature_dimension: int
|
107
107
|
reps: int
|
classiq/qmod/cfunc.py
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
from typing import Any, Callable, Dict, Optional, Union, overload
|
2
|
+
|
3
|
+
from classiq.qmod.classical_function import CFunc
|
4
|
+
|
5
|
+
|
6
|
+
def get_caller_locals() -> Dict[str, Any]:
|
7
|
+
"""Print the local variables in the caller's frame."""
|
8
|
+
import inspect
|
9
|
+
|
10
|
+
frame = inspect.currentframe()
|
11
|
+
try:
|
12
|
+
assert frame is not None
|
13
|
+
cfunc_frame = frame.f_back
|
14
|
+
assert cfunc_frame is not None
|
15
|
+
caller_frame = cfunc_frame.f_back
|
16
|
+
assert caller_frame is not None
|
17
|
+
|
18
|
+
return caller_frame.f_locals
|
19
|
+
finally:
|
20
|
+
# See here for information about the `del`
|
21
|
+
# https://docs.python.org/3/library/inspect.html#the-interpreter-stack
|
22
|
+
del frame
|
23
|
+
|
24
|
+
|
25
|
+
@overload
|
26
|
+
def cfunc(func: Callable) -> CFunc: ...
|
27
|
+
|
28
|
+
|
29
|
+
@overload
|
30
|
+
def cfunc(func: None = None) -> Callable[[Callable], CFunc]: ...
|
31
|
+
|
32
|
+
|
33
|
+
def cfunc(func: Optional[Callable] = None) -> Union[Callable[[Callable], CFunc], CFunc]:
|
34
|
+
caller_locals = get_caller_locals()
|
35
|
+
|
36
|
+
def wrapper(func: Callable) -> CFunc:
|
37
|
+
return CFunc(func, caller_locals)
|
38
|
+
|
39
|
+
if func is not None:
|
40
|
+
return wrapper(func)
|
41
|
+
|
42
|
+
return wrapper
|
@@ -2,10 +2,9 @@ import ast
|
|
2
2
|
import inspect
|
3
3
|
import sys
|
4
4
|
from textwrap import dedent
|
5
|
-
from typing import Callable
|
5
|
+
from typing import Any, Callable, Dict
|
6
6
|
|
7
7
|
from classiq.exceptions import ClassiqValueError
|
8
|
-
from classiq.qmod.builtins.classical_execution_primitives import sample, save
|
9
8
|
|
10
9
|
|
11
10
|
def _unparse_function_body(code: str, func: ast.FunctionDef) -> str:
|
@@ -18,23 +17,16 @@ def _unparse_function_body(code: str, func: ast.FunctionDef) -> str:
|
|
18
17
|
|
19
18
|
|
20
19
|
class CFunc:
|
21
|
-
|
22
|
-
def default_cmain() -> "CFunc":
|
23
|
-
@CFunc
|
24
|
-
def cmain() -> None:
|
25
|
-
result = sample()
|
26
|
-
save({"result": result})
|
27
|
-
|
28
|
-
return cmain
|
29
|
-
|
30
|
-
def __init__(self, py_callable: Callable[[], None]):
|
20
|
+
def __init__(self, py_callable: Callable[[], None], caller_locals: Dict[str, Any]):
|
31
21
|
code = dedent(inspect.getsource(py_callable))
|
32
22
|
func = ast.parse(code).body[0]
|
33
23
|
if not isinstance(func, ast.FunctionDef):
|
34
|
-
raise ClassiqValueError(
|
24
|
+
raise ClassiqValueError("Use @cfunc to decorate a function")
|
35
25
|
if len(func.args.args) > 0:
|
36
|
-
raise ClassiqValueError(
|
26
|
+
raise ClassiqValueError("A @cfunc must receive no arguments")
|
37
27
|
if sys.version_info >= (3, 9):
|
38
28
|
self.code = "\n".join([ast.unparse(statement) for statement in func.body])
|
39
29
|
else:
|
40
30
|
self.code = _unparse_function_body(code, func)
|
31
|
+
|
32
|
+
self._caller_constants = caller_locals
|
@@ -1,6 +1,5 @@
|
|
1
1
|
import dataclasses
|
2
2
|
import inspect
|
3
|
-
import sys
|
4
3
|
from typing import Any, Callable, Dict, List, Optional, Type, get_args, get_origin
|
5
4
|
|
6
5
|
from typing_extensions import _AnnotatedAlias
|
@@ -26,25 +25,17 @@ from classiq.interface.model.quantum_function_declaration import (
|
|
26
25
|
)
|
27
26
|
|
28
27
|
from classiq import StructDeclaration
|
28
|
+
from classiq.exceptions import ClassiqValueError
|
29
29
|
from classiq.qmod.model_state_container import ModelStateContainer
|
30
30
|
from classiq.qmod.qmod_parameter import Array, QParam
|
31
31
|
from classiq.qmod.qmod_variable import QVar, get_type_hint_expr
|
32
32
|
from classiq.qmod.quantum_callable import QCallable, QCallableList
|
33
|
-
from classiq.qmod.utilities import unmangle_keyword
|
33
|
+
from classiq.qmod.utilities import unmangle_keyword, version_portable_get_args
|
34
34
|
|
35
35
|
OPERAND_ARG_NAME = "arg{i}"
|
36
36
|
|
37
37
|
|
38
|
-
def
|
39
|
-
if get_origin(py_type) is None:
|
40
|
-
return tuple()
|
41
|
-
if sys.version_info[0:2] < (3, 10):
|
42
|
-
return get_args(py_type) # The result of __class_getitem__
|
43
|
-
else:
|
44
|
-
return get_args(py_type)[0]
|
45
|
-
|
46
|
-
|
47
|
-
def _python_type_to_qmod(
|
38
|
+
def python_type_to_qmod(
|
48
39
|
py_type: type, *, qmodule: ModelStateContainer
|
49
40
|
) -> Optional[ConcreteClassicalType]:
|
50
41
|
if py_type == int:
|
@@ -55,16 +46,16 @@ def _python_type_to_qmod(
|
|
55
46
|
return Bool()
|
56
47
|
elif get_origin(py_type) == list:
|
57
48
|
return ClassicalList(
|
58
|
-
element_type=
|
49
|
+
element_type=python_type_to_qmod(get_args(py_type)[0], qmodule=qmodule)
|
59
50
|
)
|
60
51
|
elif get_origin(py_type) == Array:
|
61
|
-
array_args =
|
52
|
+
array_args = version_portable_get_args(py_type)
|
62
53
|
if len(array_args) != 2:
|
63
|
-
raise
|
54
|
+
raise ClassiqValueError(
|
64
55
|
"Array accepts two generic parameters in the form 'Array[<element-type>, <size>]'"
|
65
56
|
)
|
66
57
|
return ClassicalArray(
|
67
|
-
element_type=
|
58
|
+
element_type=python_type_to_qmod(array_args[0], qmodule=qmodule),
|
68
59
|
size=get_type_hint_expr(array_args[1]),
|
69
60
|
)
|
70
61
|
elif inspect.isclass(py_type) and issubclass(py_type, QStructBase):
|
@@ -78,14 +69,14 @@ def _add_qmod_struct(
|
|
78
69
|
) -> None:
|
79
70
|
if (
|
80
71
|
py_type.__name__ in StructDeclaration.BUILTIN_STRUCT_DECLARATIONS
|
81
|
-
or py_type.__name__ in qmodule.type_decls
|
72
|
+
or py_type.__name__ in qmodule.type_decls
|
82
73
|
):
|
83
74
|
return
|
84
75
|
|
85
76
|
qmodule.type_decls[py_type.__name__] = StructDeclaration(
|
86
77
|
name=py_type.__name__,
|
87
78
|
variables={
|
88
|
-
f.name:
|
79
|
+
f.name: python_type_to_qmod(f.type, qmodule=qmodule)
|
89
80
|
for f in dataclasses.fields(py_type)
|
90
81
|
},
|
91
82
|
)
|
@@ -95,10 +86,10 @@ def _extract_param_decl(
|
|
95
86
|
name: str, py_type: Any, *, qmodule: ModelStateContainer
|
96
87
|
) -> ClassicalParameterDeclaration:
|
97
88
|
if len(get_args(py_type)) != 1:
|
98
|
-
raise
|
89
|
+
raise ClassiqValueError("QParam takes exactly one generic argument")
|
99
90
|
py_type = get_args(py_type)[0]
|
100
91
|
return ClassicalParameterDeclaration(
|
101
|
-
name=name, classical_type=
|
92
|
+
name=name, classical_type=python_type_to_qmod(py_type, qmodule=qmodule)
|
102
93
|
)
|
103
94
|
|
104
95
|
|
@@ -118,7 +109,7 @@ def _extract_port_decl(name: str, py_type: Any) -> PortDeclaration:
|
|
118
109
|
def _extract_operand_decl(
|
119
110
|
name: str, py_type: Any, qmodule: ModelStateContainer
|
120
111
|
) -> QuantumOperandDeclaration:
|
121
|
-
qc_args =
|
112
|
+
qc_args = version_portable_get_args(py_type)
|
122
113
|
arg_dict = {
|
123
114
|
OPERAND_ARG_NAME.format(i=i): arg_type for i, arg_type in enumerate(qc_args)
|
124
115
|
}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
from typing import TYPE_CHECKING, List, Tuple
|
2
|
+
|
3
|
+
from classiq.interface.generator.arith.arithmetic import compute_arithmetic_result_type
|
4
|
+
from classiq.interface.generator.arith.number_utils import MAXIMAL_MACHINE_PRECISION
|
5
|
+
from classiq.interface.model.quantum_type import QuantumNumeric
|
6
|
+
|
7
|
+
from classiq.qmod.qmod_variable import QNum
|
8
|
+
from classiq.qmod.symbolic_type import SymbolicTypes
|
9
|
+
|
10
|
+
|
11
|
+
def get_expression_numeric_attributes(
|
12
|
+
vars: List[QNum],
|
13
|
+
expr: SymbolicTypes,
|
14
|
+
machine_precision: int = MAXIMAL_MACHINE_PRECISION,
|
15
|
+
) -> Tuple[int, bool, int]:
|
16
|
+
res_type = compute_arithmetic_result_type(
|
17
|
+
expr_str=str(expr),
|
18
|
+
var_types={var._name: var.get_qmod_type() for var in vars},
|
19
|
+
machine_precision=machine_precision,
|
20
|
+
)
|
21
|
+
if TYPE_CHECKING:
|
22
|
+
assert isinstance(res_type, QuantumNumeric)
|
23
|
+
return res_type.size_in_bits, res_type.sign_value, res_type.fraction_digits_value
|
@@ -1,5 +1,6 @@
|
|
1
1
|
from typing import Dict
|
2
2
|
|
3
|
+
from classiq.interface.generator.constant import Constant
|
3
4
|
from classiq.interface.model.native_function_definition import NativeFunctionDefinition
|
4
5
|
|
5
6
|
from classiq import StructDeclaration
|
@@ -8,6 +9,7 @@ from classiq import StructDeclaration
|
|
8
9
|
class ModelStateContainer:
|
9
10
|
type_decls: Dict[str, StructDeclaration]
|
10
11
|
native_defs: Dict[str, NativeFunctionDefinition]
|
12
|
+
constants: Dict[str, Constant]
|
11
13
|
|
12
14
|
|
13
15
|
QMODULE = ModelStateContainer()
|
File without changes
|