classiq 0.52.0__py3-none-any.whl → 0.54.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 +1 -3
- classiq/_analyzer_extras/_ipywidgets_async_extension.py +2 -1
- classiq/_internals/__init__.py +0 -20
- classiq/_internals/api_wrapper.py +23 -17
- classiq/_internals/async_utils.py +1 -3
- classiq/_internals/authentication/auth0.py +5 -5
- classiq/_internals/authentication/device.py +5 -4
- classiq/_internals/authentication/password_manager.py +3 -3
- classiq/_internals/authentication/token_manager.py +3 -2
- classiq/_internals/client.py +11 -13
- classiq/_internals/config.py +2 -2
- classiq/_internals/jobs.py +7 -6
- classiq/_internals/type_validation.py +9 -9
- classiq/analyzer/__init__.py +1 -3
- classiq/analyzer/analyzer.py +8 -7
- classiq/analyzer/analyzer_utilities.py +8 -8
- classiq/analyzer/rb.py +11 -11
- classiq/applications/__init__.py +1 -3
- classiq/applications/chemistry/__init__.py +1 -3
- classiq/applications/chemistry/ansatz_parameters.py +4 -4
- classiq/applications/chemistry/chemistry_model_constructor.py +10 -9
- classiq/applications/combinatorial_helpers/combinatorial_problem_utils.py +26 -9
- classiq/applications/combinatorial_helpers/encoding_mapping.py +10 -10
- classiq/applications/combinatorial_helpers/encoding_utils.py +4 -4
- classiq/applications/combinatorial_helpers/memory.py +5 -7
- classiq/applications/combinatorial_helpers/optimization_model.py +43 -24
- classiq/applications/combinatorial_helpers/pauli_helpers/pauli_utils.py +4 -6
- classiq/applications/combinatorial_helpers/pyomo_utils.py +95 -24
- classiq/applications/combinatorial_helpers/sympy_utils.py +2 -2
- classiq/applications/combinatorial_helpers/transformations/encoding.py +8 -8
- classiq/applications/combinatorial_helpers/transformations/fixed_variables.py +5 -5
- classiq/applications/combinatorial_helpers/transformations/ising_converter.py +7 -9
- classiq/applications/combinatorial_helpers/transformations/penalty.py +1 -2
- classiq/applications/combinatorial_helpers/transformations/sign_seperation.py +1 -2
- classiq/applications/combinatorial_helpers/transformations/slack_variables.py +1 -2
- classiq/applications/combinatorial_optimization/__init__.py +1 -3
- classiq/applications/combinatorial_optimization/combinatorial_optimization_config.py +2 -2
- classiq/applications/combinatorial_optimization/examples/__init__.py +1 -3
- classiq/applications/finance/__init__.py +1 -3
- classiq/applications/grover/__init__.py +1 -3
- classiq/applications/grover/grover_model_constructor.py +7 -9
- classiq/applications/hamiltonian/pauli_decomposition.py +6 -6
- classiq/applications/qnn/__init__.py +1 -3
- classiq/applications/qnn/circuit_utils.py +5 -5
- classiq/applications/qnn/datasets/__init__.py +1 -3
- classiq/applications/qnn/datasets/dataset_base_classes.py +5 -4
- classiq/applications/qnn/datasets/dataset_parity.py +2 -2
- classiq/applications/qnn/gradients/simple_quantum_gradient.py +2 -1
- classiq/applications/qnn/qlayer.py +25 -6
- classiq/applications/qnn/torch_utils.py +2 -2
- classiq/applications/qnn/types.py +5 -5
- classiq/applications/qsvm/qsvm.py +1 -3
- classiq/applications/qsvm/qsvm_data_generation.py +3 -3
- classiq/applications/qsvm/qsvm_model_constructor.py +5 -5
- classiq/execution/__init__.py +3 -3
- classiq/execution/all_hardware_devices.py +1 -3
- classiq/execution/execution_session.py +57 -16
- classiq/execution/iqcc.py +1 -1
- classiq/execution/jobs.py +4 -4
- classiq/execution/qaoa.py +84 -0
- classiq/execution/qnn.py +3 -3
- classiq/executor.py +4 -4
- classiq/interface/_version.py +1 -1
- classiq/interface/analyzer/analysis_params.py +9 -10
- classiq/interface/analyzer/cytoscape_graph.py +5 -5
- classiq/interface/analyzer/result.py +17 -17
- classiq/interface/applications/qsvm.py +6 -10
- classiq/interface/backend/backend_preferences.py +4 -3
- classiq/interface/backend/ionq/ionq_quantum_program.py +4 -5
- classiq/interface/backend/pydantic_backend.py +1 -2
- classiq/interface/chemistry/fermionic_operator.py +5 -5
- classiq/interface/chemistry/ground_state_problem.py +7 -8
- classiq/interface/chemistry/molecule.py +4 -4
- classiq/interface/chemistry/operator.py +11 -13
- classiq/interface/combinatorial_optimization/examples/ascending_sequence.py +1 -3
- classiq/interface/combinatorial_optimization/examples/integer_portfolio_optimization.py +2 -4
- classiq/interface/combinatorial_optimization/examples/knapsack.py +3 -3
- classiq/interface/combinatorial_optimization/examples/mht.py +2 -3
- classiq/interface/combinatorial_optimization/examples/portfolio_variations.py +2 -2
- classiq/interface/combinatorial_optimization/examples/set_cover.py +1 -2
- classiq/interface/combinatorial_optimization/mht_qaoa_input.py +5 -7
- classiq/interface/combinatorial_optimization/optimization_problem.py +2 -2
- classiq/interface/combinatorial_optimization/result.py +1 -3
- classiq/interface/debug_info/debug_info.py +8 -7
- classiq/interface/exceptions.py +11 -7
- classiq/interface/execution/iqcc.py +1 -3
- classiq/interface/execution/jobs.py +2 -2
- classiq/interface/execution/primitives.py +3 -3
- classiq/interface/executor/aws_execution_cost.py +4 -4
- classiq/interface/executor/execution_request.py +2 -3
- classiq/interface/executor/execution_result.py +3 -3
- classiq/interface/executor/iqae_result.py +3 -5
- classiq/interface/executor/optimizer_preferences.py +2 -2
- classiq/interface/executor/quantum_code.py +6 -6
- classiq/interface/executor/register_initialization.py +2 -4
- classiq/interface/executor/result.py +35 -28
- classiq/interface/executor/vqe_result.py +8 -8
- classiq/interface/finance/function_input.py +2 -2
- classiq/interface/finance/gaussian_model_input.py +5 -5
- classiq/interface/finance/log_normal_model_input.py +2 -2
- classiq/interface/finance/model_input.py +1 -2
- classiq/interface/generator/adjacency.py +1 -3
- classiq/interface/generator/ansatz_library.py +4 -4
- classiq/interface/generator/application_apis/finance_declarations.py +1 -1
- classiq/interface/generator/arith/argument_utils.py +3 -3
- classiq/interface/generator/arith/arithmetic.py +7 -7
- classiq/interface/generator/arith/arithmetic_arg_type_validator.py +5 -5
- classiq/interface/generator/arith/arithmetic_expression_abc.py +11 -11
- classiq/interface/generator/arith/arithmetic_expression_parser.py +8 -7
- classiq/interface/generator/arith/arithmetic_expression_validator.py +8 -8
- classiq/interface/generator/arith/arithmetic_operations.py +4 -3
- classiq/interface/generator/arith/arithmetic_param_getters.py +6 -6
- classiq/interface/generator/arith/arithmetic_result_builder.py +9 -9
- classiq/interface/generator/arith/ast_node_rewrite.py +2 -1
- classiq/interface/generator/arith/binary_ops.py +10 -13
- classiq/interface/generator/arith/extremum_operations.py +3 -2
- classiq/interface/generator/arith/logical_ops.py +7 -6
- classiq/interface/generator/arith/number_utils.py +4 -4
- classiq/interface/generator/arith/register_user_input.py +4 -4
- classiq/interface/generator/arith/unary_ops.py +2 -1
- classiq/interface/generator/builtin_api_builder.py +2 -1
- classiq/interface/generator/circuit_code/circuit_code.py +4 -4
- classiq/interface/generator/circuit_code/types_and_constants.py +3 -5
- classiq/interface/generator/complex_type.py +1 -2
- classiq/interface/generator/control_state.py +2 -2
- classiq/interface/generator/custom_ansatz.py +1 -3
- classiq/interface/generator/distance.py +3 -5
- classiq/interface/generator/excitations.py +3 -2
- classiq/interface/generator/expressions/enums/finance_functions.py +1 -3
- classiq/interface/generator/expressions/evaluated_expression.py +4 -3
- classiq/interface/generator/expressions/expression.py +4 -5
- classiq/interface/generator/expressions/expression_constants.py +4 -4
- classiq/interface/generator/expressions/qmod_qarray_proxy.py +2 -1
- classiq/interface/generator/expressions/qmod_qscalar_proxy.py +2 -1
- classiq/interface/generator/expressions/qmod_qstruct_proxy.py +2 -1
- classiq/interface/generator/expressions/qmod_sized_proxy.py +2 -1
- classiq/interface/generator/expressions/qmod_struct_instance.py +2 -1
- classiq/interface/generator/expressions/sympy_supported_expressions.py +11 -13
- classiq/interface/generator/finance.py +2 -2
- classiq/interface/generator/function_param_library.py +6 -6
- classiq/interface/generator/function_params.py +13 -19
- classiq/interface/generator/functions/classical_function_declaration.py +4 -3
- classiq/interface/generator/functions/classical_type.py +13 -13
- classiq/interface/generator/functions/concrete_types.py +1 -2
- classiq/interface/generator/functions/function_declaration.py +1 -1
- classiq/interface/generator/functions/qmod_python_interface.py +2 -1
- classiq/interface/generator/functions/type_name.py +3 -2
- classiq/interface/generator/generated_circuit_data.py +34 -22
- classiq/interface/generator/grover_diffuser.py +7 -7
- classiq/interface/generator/grover_operator.py +2 -2
- classiq/interface/generator/hardware/hardware_data.py +7 -6
- classiq/interface/generator/hardware_efficient_ansatz.py +8 -8
- classiq/interface/generator/identity.py +5 -6
- classiq/interface/generator/linear_pauli_rotations.py +6 -6
- classiq/interface/generator/mcu.py +2 -2
- classiq/interface/generator/mcx.py +6 -6
- classiq/interface/generator/model/__init__.py +1 -3
- classiq/interface/generator/model/constraints.py +2 -2
- classiq/interface/generator/model/model.py +5 -6
- classiq/interface/generator/model/preferences/preferences.py +7 -6
- classiq/interface/generator/model/quantum_register.py +6 -11
- classiq/interface/generator/oracles/arithmetic_oracle.py +1 -2
- classiq/interface/generator/oracles/custom_oracle.py +2 -2
- classiq/interface/generator/oracles/oracle_abc.py +6 -5
- classiq/interface/generator/partitioned_register.py +6 -5
- classiq/interface/generator/piecewise_linear_amplitude_loading.py +8 -7
- classiq/interface/generator/qpe.py +4 -4
- classiq/interface/generator/qsvm.py +3 -3
- classiq/interface/generator/quantum_function_call.py +24 -29
- classiq/interface/generator/quantum_program.py +9 -9
- classiq/interface/generator/register_role.py +2 -4
- classiq/interface/generator/slice_parsing_utils.py +4 -3
- classiq/interface/generator/standard_gates/standard_gates.py +3 -3
- classiq/interface/generator/state_preparation/bell_state_preparation.py +3 -3
- classiq/interface/generator/state_preparation/distributions.py +6 -5
- classiq/interface/generator/state_preparation/metrics.py +2 -4
- classiq/interface/generator/state_preparation/state_preparation.py +4 -4
- classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +3 -3
- classiq/interface/generator/transpiler_basis_gates.py +2 -2
- classiq/interface/generator/types/enum_declaration.py +2 -3
- classiq/interface/generator/types/qstruct_declaration.py +2 -1
- classiq/interface/generator/types/struct_declaration.py +3 -2
- classiq/interface/generator/ucc.py +2 -1
- classiq/interface/generator/unitary_gate.py +2 -2
- classiq/interface/generator/user_defined_function_params.py +1 -1
- classiq/interface/generator/validations/flow_graph.py +6 -5
- classiq/interface/generator/validations/validator_functions.py +3 -2
- classiq/interface/generator/visitor.py +9 -14
- classiq/interface/hardware.py +5 -6
- classiq/interface/helpers/custom_encoders.py +2 -2
- classiq/interface/helpers/custom_pydantic_types.py +8 -9
- classiq/interface/helpers/dotdict.py +18 -0
- classiq/interface/helpers/hashable_mixin.py +3 -2
- classiq/interface/helpers/hashable_pydantic_base_model.py +2 -1
- classiq/interface/helpers/pydantic_model_helpers.py +4 -3
- classiq/interface/helpers/validation_helpers.py +2 -2
- classiq/interface/ide/ide_data.py +11 -15
- classiq/interface/ide/visual_model.py +33 -22
- classiq/interface/jobs.py +2 -2
- classiq/interface/model/bind_operation.py +5 -4
- classiq/interface/model/classical_parameter_declaration.py +2 -2
- classiq/interface/model/handle_binding.py +3 -2
- classiq/interface/model/inplace_binary_operation.py +2 -1
- classiq/interface/model/model.py +12 -11
- classiq/interface/model/native_function_definition.py +10 -0
- classiq/interface/model/port_declaration.py +2 -2
- classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +3 -2
- classiq/interface/model/quantum_expressions/arithmetic_operation.py +3 -2
- classiq/interface/model/quantum_expressions/quantum_expression.py +8 -7
- classiq/interface/model/quantum_function_call.py +9 -14
- classiq/interface/model/quantum_function_declaration.py +10 -12
- classiq/interface/model/quantum_lambda_function.py +3 -16
- classiq/interface/model/quantum_statement.py +4 -3
- classiq/interface/model/quantum_type.py +5 -5
- classiq/interface/model/statement_block.py +2 -3
- classiq/interface/model/validation_handle.py +5 -4
- classiq/interface/server/global_versions.py +3 -3
- classiq/model_expansions/atomic_expression_functions_defs.py +3 -2
- classiq/model_expansions/call_to_model_converter.py +190 -0
- classiq/model_expansions/capturing/captured_var_manager.py +4 -6
- classiq/model_expansions/capturing/propagated_var_stack.py +7 -7
- classiq/model_expansions/closure.py +17 -9
- classiq/model_expansions/evaluators/arg_type_match.py +3 -2
- classiq/model_expansions/evaluators/argument_types.py +3 -3
- classiq/model_expansions/evaluators/control.py +3 -3
- classiq/model_expansions/evaluators/parameter_types.py +7 -7
- classiq/model_expansions/evaluators/quantum_type_utils.py +2 -1
- classiq/model_expansions/evaluators/type_type_match.py +1 -1
- classiq/model_expansions/expression_evaluator.py +10 -9
- classiq/model_expansions/expression_renamer.py +6 -6
- classiq/model_expansions/function_builder.py +19 -12
- classiq/model_expansions/generative_functions.py +3 -2
- classiq/model_expansions/interpreter.py +31 -19
- classiq/model_expansions/model_tables.py +14 -14
- classiq/model_expansions/quantum_operations/bind.py +2 -4
- classiq/model_expansions/quantum_operations/classicalif.py +1 -1
- classiq/model_expansions/quantum_operations/control.py +2 -4
- classiq/model_expansions/quantum_operations/emitter.py +10 -13
- classiq/model_expansions/quantum_operations/expression_operation.py +23 -16
- classiq/model_expansions/quantum_operations/inplace_binary_operation.py +164 -38
- classiq/model_expansions/quantum_operations/phase.py +6 -6
- classiq/model_expansions/quantum_operations/quantum_assignment_operation.py +25 -5
- classiq/model_expansions/quantum_operations/quantum_function_call.py +41 -2
- classiq/model_expansions/quantum_operations/repeat.py +1 -3
- classiq/model_expansions/scope.py +11 -10
- classiq/model_expansions/scope_initialization.py +6 -5
- classiq/model_expansions/sympy_conversion/expression_to_sympy.py +6 -6
- classiq/model_expansions/sympy_conversion/sympy_to_python.py +2 -2
- classiq/model_expansions/visitors/variable_references.py +5 -4
- classiq/qmod/__init__.py +2 -0
- classiq/qmod/builtins/classical_execution_primitives.py +9 -9
- classiq/qmod/builtins/functions/__init__.py +75 -53
- classiq/qmod/builtins/functions/amplitude_estimation.py +4 -1
- classiq/qmod/builtins/functions/arithmetic.py +14 -1
- classiq/qmod/builtins/functions/discrete_sine_cosine_transform.py +86 -6
- classiq/qmod/builtins/functions/grover.py +41 -45
- classiq/qmod/builtins/functions/hea.py +60 -4
- classiq/qmod/builtins/functions/linear_pauli_rotation.py +26 -4
- classiq/qmod/builtins/functions/modular_exponentiation.py +90 -29
- classiq/qmod/builtins/functions/operators.py +1 -1
- classiq/qmod/builtins/functions/qaoa_penalty.py +14 -5
- classiq/qmod/builtins/functions/qft_functions.py +57 -0
- classiq/qmod/builtins/functions/qpe.py +20 -4
- classiq/qmod/builtins/functions/qsvt.py +49 -4
- classiq/qmod/builtins/functions/standard_gates.py +18 -18
- classiq/qmod/builtins/functions/state_preparation.py +92 -10
- classiq/qmod/builtins/functions/swap_test.py +7 -1
- classiq/qmod/builtins/functions/utility_functions.py +43 -0
- classiq/qmod/builtins/functions/variational.py +53 -0
- classiq/qmod/builtins/operations.py +4 -5
- classiq/qmod/cfunc.py +2 -2
- classiq/qmod/classical_function.py +3 -7
- classiq/qmod/create_model_function.py +19 -8
- classiq/qmod/declaration_inferrer.py +7 -10
- classiq/qmod/expression_query.py +3 -3
- classiq/qmod/generative.py +2 -1
- classiq/qmod/model_state_container.py +5 -7
- classiq/qmod/native/__init__.py +1 -3
- classiq/qmod/native/expression_to_qmod.py +9 -8
- classiq/qmod/native/pretty_printer.py +6 -5
- classiq/qmod/pretty_print/__init__.py +1 -3
- classiq/qmod/pretty_print/expression_to_python.py +13 -12
- classiq/qmod/pretty_print/pretty_printer.py +13 -12
- classiq/qmod/python_classical_type.py +8 -4
- classiq/qmod/qfunc.py +4 -4
- classiq/qmod/qmod_parameter.py +3 -1
- classiq/qmod/qmod_variable.py +11 -10
- classiq/qmod/quantum_expandable.py +32 -15
- classiq/qmod/quantum_function.py +34 -5
- classiq/qmod/semantics/annotation.py +1 -1
- classiq/qmod/semantics/error_manager.py +8 -7
- classiq/qmod/semantics/static_semantics_visitor.py +19 -24
- classiq/qmod/semantics/validation/constants_validation.py +1 -1
- classiq/qmod/semantics/validation/func_call_validation.py +2 -2
- classiq/qmod/semantics/validation/main_validation.py +33 -0
- classiq/qmod/semantics/validation/types_validation.py +2 -1
- classiq/qmod/symbolic.py +5 -8
- classiq/qmod/symbolic_type.py +2 -2
- classiq/qmod/synthesize_separately.py +16 -0
- {classiq-0.52.0.dist-info → classiq-0.54.0.dist-info}/METADATA +1 -1
- {classiq-0.52.0.dist-info → classiq-0.54.0.dist-info}/RECORD +302 -295
- classiq/qmod/builtins/functions/qft.py +0 -23
- {classiq-0.52.0.dist-info → classiq-0.54.0.dist-info}/WHEEL +0 -0
@@ -1,5 +1,3 @@
|
|
1
|
-
from typing import List
|
2
|
-
|
3
1
|
from classiq.interface.exceptions import ClassiqExpansionError
|
4
2
|
from classiq.interface.model.bind_operation import BindOperation
|
5
3
|
|
@@ -18,11 +16,11 @@ class BindEmitter(Emitter[BindOperation]):
|
|
18
16
|
def emit(self, bind: BindOperation, /) -> None:
|
19
17
|
with self._propagated_var_stack.capture_variables(bind):
|
20
18
|
pass
|
21
|
-
inputs:
|
19
|
+
inputs: list[QuantumSymbol] = [
|
22
20
|
self._interpreter.evaluate(arg).as_type(QuantumSymbol)
|
23
21
|
for arg in bind.in_handles
|
24
22
|
]
|
25
|
-
outputs:
|
23
|
+
outputs: list[QuantumSymbol] = [
|
26
24
|
self._interpreter.evaluate(arg).as_type(QuantumSymbol)
|
27
25
|
for arg in bind.out_handles
|
28
26
|
]
|
@@ -1,5 +1,3 @@
|
|
1
|
-
from typing import List, Tuple
|
2
|
-
|
3
1
|
from sympy import Equality
|
4
2
|
from sympy.logic.boolalg import Boolean
|
5
3
|
from typing_extensions import TypeGuard
|
@@ -160,7 +158,7 @@ class ControlEmitter(ExpressionOperationEmitter[Control]):
|
|
160
158
|
def _emit_with_x_gates(
|
161
159
|
self, control: Control, ctrl: QmodSizedProxy, ctrl_state: str
|
162
160
|
) -> None:
|
163
|
-
compute_op:
|
161
|
+
compute_op: list[ConcreteQuantumStatement] = []
|
164
162
|
|
165
163
|
x_gate_value = self._get_x_gate_value(ctrl_state)
|
166
164
|
if x_gate_value != 0:
|
@@ -194,7 +192,7 @@ class ControlEmitter(ExpressionOperationEmitter[Control]):
|
|
194
192
|
|
195
193
|
def _get_array_cast_ops(
|
196
194
|
self, ctrl: QmodQNumProxy
|
197
|
-
) ->
|
195
|
+
) -> tuple[VariableDeclarationStatement, BindOperation]:
|
198
196
|
array_cast = self._counted_name_allocator.allocate(
|
199
197
|
f"{ctrl.handle}{ARRAY_CAST_SUFFIX}"
|
200
198
|
)
|
@@ -1,11 +1,9 @@
|
|
1
1
|
from abc import abstractmethod
|
2
|
+
from collections.abc import Sequence
|
2
3
|
from typing import (
|
3
4
|
TYPE_CHECKING,
|
4
|
-
Dict,
|
5
5
|
Generic,
|
6
|
-
List,
|
7
6
|
Optional,
|
8
|
-
Sequence,
|
9
7
|
TypeVar,
|
10
8
|
Union,
|
11
9
|
cast,
|
@@ -18,7 +16,7 @@ from classiq.interface.generator.expressions.evaluated_expression import (
|
|
18
16
|
EvaluatedExpression,
|
19
17
|
)
|
20
18
|
from classiq.interface.generator.expressions.expression import Expression
|
21
|
-
from classiq.interface.
|
19
|
+
from classiq.interface.generator.generated_circuit_data import OperationLevel
|
22
20
|
from classiq.interface.model.classical_parameter_declaration import (
|
23
21
|
ClassicalParameterDeclaration,
|
24
22
|
)
|
@@ -63,7 +61,6 @@ from classiq.qmod.quantum_function import GenerativeQFunc
|
|
63
61
|
if TYPE_CHECKING:
|
64
62
|
from classiq.model_expansions.interpreter import Interpreter
|
65
63
|
|
66
|
-
|
67
64
|
QuantumStatementT = TypeVar("QuantumStatementT", bound=QuantumStatement)
|
68
65
|
|
69
66
|
|
@@ -74,7 +71,7 @@ class Emitter(Generic[QuantumStatementT]):
|
|
74
71
|
self._scope_guard = self._interpreter._scope_guard
|
75
72
|
self._machine_precision = self._interpreter._model.preferences.machine_precision
|
76
73
|
|
77
|
-
self._generative_contexts:
|
74
|
+
self._generative_contexts: dict[str, OperationContext] = {}
|
78
75
|
|
79
76
|
@abstractmethod
|
80
77
|
def emit(self, statement: QuantumStatementT, /) -> None:
|
@@ -103,7 +100,7 @@ class Emitter(Generic[QuantumStatementT]):
|
|
103
100
|
return self._interpreter._current_scope
|
104
101
|
|
105
102
|
@property
|
106
|
-
def _expanded_functions(self) ->
|
103
|
+
def _expanded_functions(self) -> list[NativeFunctionDefinition]:
|
107
104
|
return self._interpreter._expanded_functions
|
108
105
|
|
109
106
|
@property
|
@@ -125,14 +122,14 @@ class Emitter(Generic[QuantumStatementT]):
|
|
125
122
|
return self._create_quantum_function_call(wrapping_function, list())
|
126
123
|
|
127
124
|
def _emit_quantum_function_call(
|
128
|
-
self, function: FunctionClosure, args:
|
125
|
+
self, function: FunctionClosure, args: list[ArgValue]
|
129
126
|
) -> QuantumFunctionCall:
|
130
127
|
call = self._create_quantum_function_call(function, args)
|
131
128
|
self._builder.emit_statement(call)
|
132
129
|
return call
|
133
130
|
|
134
131
|
def _create_quantum_function_call(
|
135
|
-
self, function: FunctionClosure, args:
|
132
|
+
self, function: FunctionClosure, args: list[ArgValue]
|
136
133
|
) -> QuantumFunctionCall:
|
137
134
|
evaluated_args = [self._interpreter.evaluate(arg) for arg in args]
|
138
135
|
new_declaration = self._prepare_fully_typed_declaration(
|
@@ -206,10 +203,10 @@ class Emitter(Generic[QuantumStatementT]):
|
|
206
203
|
|
207
204
|
def _get_new_positional_args(
|
208
205
|
self,
|
209
|
-
evaluated_args:
|
206
|
+
evaluated_args: list[Evaluated],
|
210
207
|
is_atomic: bool,
|
211
208
|
new_positional_arg_decls: Sequence[PositionalArg],
|
212
|
-
) ->
|
209
|
+
) -> list[ArgValue]:
|
213
210
|
evaluated_args = add_information_from_output_arguments(
|
214
211
|
new_positional_arg_decls, evaluated_args
|
215
212
|
)
|
@@ -230,7 +227,7 @@ class Emitter(Generic[QuantumStatementT]):
|
|
230
227
|
return positional_args
|
231
228
|
|
232
229
|
def _prepare_fully_typed_declaration(
|
233
|
-
self, function: FunctionClosure, evaluated_args:
|
230
|
+
self, function: FunctionClosure, evaluated_args: list[Evaluated]
|
234
231
|
) -> NamedParamsQuantumFunctionDeclaration:
|
235
232
|
"""
|
236
233
|
Given, for example,
|
@@ -260,7 +257,7 @@ class Emitter(Generic[QuantumStatementT]):
|
|
260
257
|
self,
|
261
258
|
op: QuantumOperation,
|
262
259
|
context_name: str,
|
263
|
-
block_names: Union[None, str,
|
260
|
+
block_names: Union[None, str, list[str]] = None,
|
264
261
|
func_decl: Optional[NamedParamsQuantumFunctionDeclaration] = None,
|
265
262
|
) -> OperationContext:
|
266
263
|
if isinstance(block_names, str):
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import ast
|
2
2
|
from abc import abstractmethod
|
3
3
|
from itertools import chain
|
4
|
-
from typing import TYPE_CHECKING,
|
4
|
+
from typing import TYPE_CHECKING, TypeVar
|
5
5
|
|
6
6
|
from classiq.interface.exceptions import (
|
7
7
|
ClassiqExpansionError,
|
@@ -26,6 +26,7 @@ from classiq.interface.model.quantum_type import (
|
|
26
26
|
QuantumBit,
|
27
27
|
QuantumBitvector,
|
28
28
|
QuantumNumeric,
|
29
|
+
QuantumType,
|
29
30
|
)
|
30
31
|
from classiq.interface.model.variable_declaration_statement import (
|
31
32
|
VariableDeclarationStatement,
|
@@ -48,7 +49,7 @@ class ExpressionOperationEmitter(Emitter[ExpressionOperationT]):
|
|
48
49
|
self,
|
49
50
|
op: ExpressionOperationT,
|
50
51
|
expression: Expression,
|
51
|
-
symbols_to_split:
|
52
|
+
symbols_to_split: list[QuantumSymbol],
|
52
53
|
) -> None:
|
53
54
|
symbols_parts, bind_ops = self._get_bind_ops(symbols_to_split)
|
54
55
|
|
@@ -62,14 +63,13 @@ class ExpressionOperationEmitter(Emitter[ExpressionOperationT]):
|
|
62
63
|
)
|
63
64
|
)
|
64
65
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
expression,
|
71
|
-
)
|
66
|
+
symbol_mapping = {
|
67
|
+
symbol.handle: (symbol_part_var_name, symbol.quantum_type)
|
68
|
+
for symbol, symbol_part_var_name in chain.from_iterable(symbols_parts)
|
69
|
+
}
|
70
|
+
new_expression = self._update_op_expression(symbol_mapping, expression)
|
72
71
|
new_op = op.model_copy(update=dict(expression=new_expression))
|
72
|
+
new_op = self._get_updated_op_split_symbols(new_op, symbol_mapping)
|
73
73
|
|
74
74
|
self._interpreter.emit_statement(
|
75
75
|
WithinApply(
|
@@ -79,9 +79,16 @@ class ExpressionOperationEmitter(Emitter[ExpressionOperationT]):
|
|
79
79
|
)
|
80
80
|
)
|
81
81
|
|
82
|
+
@staticmethod
|
83
|
+
def _get_updated_op_split_symbols(
|
84
|
+
op: ExpressionOperationT,
|
85
|
+
symbol_mapping: dict[HandleBinding, tuple[str, QuantumType]],
|
86
|
+
) -> ExpressionOperationT:
|
87
|
+
return op
|
88
|
+
|
82
89
|
def _update_op_expression(
|
83
90
|
self,
|
84
|
-
|
91
|
+
symbol_mapping: dict[HandleBinding, tuple[str, QuantumType]],
|
85
92
|
expression: Expression,
|
86
93
|
) -> Expression:
|
87
94
|
vrc = VarRefCollector(ignore_duplicated_handles=True)
|
@@ -90,9 +97,9 @@ class ExpressionOperationEmitter(Emitter[ExpressionOperationT]):
|
|
90
97
|
new_expr_str = expression.expr
|
91
98
|
for handle in vrc.var_handles:
|
92
99
|
collapsed_handle = handle.collapse()
|
93
|
-
if collapsed_handle in
|
100
|
+
if collapsed_handle in symbol_mapping:
|
94
101
|
new_expr_str = new_expr_str.replace(
|
95
|
-
str(handle),
|
102
|
+
str(handle), symbol_mapping[collapsed_handle][0]
|
96
103
|
)
|
97
104
|
self._check_all_handles_were_replaced(new_expr_str)
|
98
105
|
|
@@ -115,8 +122,8 @@ class ExpressionOperationEmitter(Emitter[ExpressionOperationT]):
|
|
115
122
|
|
116
123
|
def _get_bind_ops(
|
117
124
|
self,
|
118
|
-
symbols_to_split:
|
119
|
-
) ->
|
125
|
+
symbols_to_split: list[QuantumSymbol],
|
126
|
+
) -> tuple[list[list[tuple[QuantumSymbol, str]]], list[BindOperation]]:
|
120
127
|
bind_ops = []
|
121
128
|
symbols_parts = []
|
122
129
|
for symbol in symbols_to_split:
|
@@ -135,7 +142,7 @@ class ExpressionOperationEmitter(Emitter[ExpressionOperationT]):
|
|
135
142
|
|
136
143
|
def _get_symbol_parts(
|
137
144
|
self, symbol: QuantumSymbol
|
138
|
-
) ->
|
145
|
+
) -> list[tuple[QuantumSymbol, str]]:
|
139
146
|
quantum_type = symbol.quantum_type
|
140
147
|
|
141
148
|
if isinstance(quantum_type, (QuantumBit, QuantumNumeric)):
|
@@ -169,7 +176,7 @@ class ExpressionOperationEmitter(Emitter[ExpressionOperationT]):
|
|
169
176
|
)
|
170
177
|
)
|
171
178
|
|
172
|
-
def _get_symbols_to_split(self, expression: Expression) ->
|
179
|
+
def _get_symbols_to_split(self, expression: Expression) -> list[QuantumSymbol]:
|
173
180
|
vrc = VarRefCollector(ignore_duplicated_handles=True)
|
174
181
|
vrc.visit(ast.parse(expression.expr))
|
175
182
|
symbol_names_to_split = dict.fromkeys(
|
@@ -1,10 +1,12 @@
|
|
1
|
-
from typing import TYPE_CHECKING,
|
1
|
+
from typing import TYPE_CHECKING, Optional, Union
|
2
2
|
|
3
|
+
from classiq.interface.exceptions import ClassiqInternalExpansionError
|
3
4
|
from classiq.interface.generator.expressions.expression import Expression
|
4
5
|
from classiq.interface.generator.functions.port_declaration import (
|
5
6
|
PortDeclarationDirection,
|
6
7
|
)
|
7
8
|
from classiq.interface.model.bind_operation import BindOperation
|
9
|
+
from classiq.interface.model.control import Control
|
8
10
|
from classiq.interface.model.handle_binding import HandleBinding
|
9
11
|
from classiq.interface.model.inplace_binary_operation import (
|
10
12
|
BinaryOperation,
|
@@ -16,11 +18,7 @@ from classiq.interface.model.quantum_function_declaration import (
|
|
16
18
|
NamedParamsQuantumFunctionDeclaration,
|
17
19
|
)
|
18
20
|
from classiq.interface.model.quantum_statement import QuantumStatement
|
19
|
-
from classiq.interface.model.quantum_type import
|
20
|
-
QuantumBit,
|
21
|
-
QuantumBitvector,
|
22
|
-
QuantumNumeric,
|
23
|
-
)
|
21
|
+
from classiq.interface.model.quantum_type import QuantumBitvector, QuantumNumeric
|
24
22
|
from classiq.interface.model.variable_declaration_statement import (
|
25
23
|
VariableDeclarationStatement,
|
26
24
|
)
|
@@ -38,6 +36,7 @@ from classiq.model_expansions.scope import QuantumSymbol, Scope
|
|
38
36
|
from classiq.qmod.builtins.functions import (
|
39
37
|
CX,
|
40
38
|
allocate,
|
39
|
+
apply_to_all,
|
41
40
|
integer_xor,
|
42
41
|
modular_add,
|
43
42
|
modular_add_constant,
|
@@ -94,6 +93,18 @@ class InplaceBinaryOperationEmitter(Emitter[InplaceBinaryOperation]):
|
|
94
93
|
handle=HandleBinding(name="target"),
|
95
94
|
quantum_type=target_var.quantum_type,
|
96
95
|
)
|
96
|
+
internal_func_decl = _binary_function_declaration(op.operation, constant=False)
|
97
|
+
if op.operation == BinaryOperation.Xor:
|
98
|
+
body = _build_inplace_xor_operation(
|
99
|
+
value_var=value_var,
|
100
|
+
target_var=target_var,
|
101
|
+
)
|
102
|
+
else:
|
103
|
+
body = _build_inplace_binary_operation(
|
104
|
+
value_var=value_var,
|
105
|
+
target_var=target_var,
|
106
|
+
internal_function_declaration=internal_func_decl,
|
107
|
+
)
|
97
108
|
inplace_binary_op_function = FunctionClosure.create(
|
98
109
|
name=op.operation.value,
|
99
110
|
positional_arg_declarations=[
|
@@ -108,13 +119,7 @@ class InplaceBinaryOperationEmitter(Emitter[InplaceBinaryOperation]):
|
|
108
119
|
direction=PortDeclarationDirection.Inout,
|
109
120
|
),
|
110
121
|
],
|
111
|
-
body=
|
112
|
-
value_var=value_var,
|
113
|
-
target_var=target_var,
|
114
|
-
internal_function_declaration=_binary_function_declaration(
|
115
|
-
op.operation, constant=False
|
116
|
-
),
|
117
|
-
),
|
122
|
+
body=body,
|
118
123
|
scope=Scope(parent=self._current_scope),
|
119
124
|
)
|
120
125
|
with self._propagated_var_stack.capture_variables(op):
|
@@ -139,7 +144,7 @@ def _build_inplace_binary_operation(
|
|
139
144
|
value_var: QuantumSymbol,
|
140
145
|
target_var: QuantumSymbol,
|
141
146
|
internal_function_declaration: NamedParamsQuantumFunctionDeclaration,
|
142
|
-
) ->
|
147
|
+
) -> list[QuantumStatement]:
|
143
148
|
if TYPE_CHECKING:
|
144
149
|
assert isinstance(value_var.quantum_type, QuantumNumeric)
|
145
150
|
assert isinstance(target_var.quantum_type, QuantumNumeric)
|
@@ -148,9 +153,6 @@ def _build_inplace_binary_operation(
|
|
148
153
|
value_var.quantum_type.fraction_digits_value
|
149
154
|
- target_var.quantum_type.fraction_digits_value
|
150
155
|
)
|
151
|
-
size_diff = (
|
152
|
-
value_var.quantum_type.size_in_bits - target_var.quantum_type.size_in_bits
|
153
|
-
)
|
154
156
|
|
155
157
|
target_overlap_var, target_var_decls, target_bind_ops = (
|
156
158
|
_trim_superfluous_fraction_digits("target", target_var, -frac_digits_diff)
|
@@ -158,6 +160,10 @@ def _build_inplace_binary_operation(
|
|
158
160
|
value_overlap_var, value_trim_var_decls, value_bind_ops = (
|
159
161
|
_trim_superfluous_fraction_digits("value", value_var, frac_digits_diff)
|
160
162
|
)
|
163
|
+
size_diff = (
|
164
|
+
value_overlap_var.quantum_type.size_in_bits
|
165
|
+
- target_overlap_var.quantum_type.size_in_bits
|
166
|
+
)
|
161
167
|
(
|
162
168
|
value_padded_var,
|
163
169
|
value_pad_var_decls,
|
@@ -191,6 +197,54 @@ def _build_inplace_binary_operation(
|
|
191
197
|
]
|
192
198
|
|
193
199
|
|
200
|
+
def _build_inplace_xor_operation(
|
201
|
+
value_var: QuantumSymbol, target_var: QuantumSymbol
|
202
|
+
) -> list[QuantumStatement]:
|
203
|
+
if TYPE_CHECKING:
|
204
|
+
assert isinstance(value_var.quantum_type, QuantumNumeric)
|
205
|
+
assert isinstance(target_var.quantum_type, QuantumNumeric)
|
206
|
+
|
207
|
+
frac_digits_diff = (
|
208
|
+
value_var.quantum_type.fraction_digits_value
|
209
|
+
- target_var.quantum_type.fraction_digits_value
|
210
|
+
)
|
211
|
+
|
212
|
+
target_overlap_var, target_var_decls, target_bind_ops = (
|
213
|
+
_trim_superfluous_fraction_digits("target", target_var, -frac_digits_diff)
|
214
|
+
)
|
215
|
+
value_overlap_var, value_trim_var_decls, value_bind_ops = (
|
216
|
+
_trim_superfluous_fraction_digits("value", value_var, frac_digits_diff)
|
217
|
+
)
|
218
|
+
target_left_var, value_left_var, sign_var_decls, sign_bind_ops, sign_xor = (
|
219
|
+
_split_and_xor_sign(target_overlap_var, value_overlap_var)
|
220
|
+
)
|
221
|
+
|
222
|
+
action: list[QuantumStatement] = []
|
223
|
+
if target_left_var is not None and value_left_var is not None:
|
224
|
+
action.append(
|
225
|
+
_internal_inplace_binary_operation_function_call(
|
226
|
+
integer_xor.func_decl,
|
227
|
+
value_left_var.handle,
|
228
|
+
target_left_var.handle,
|
229
|
+
)
|
230
|
+
)
|
231
|
+
action.extend(sign_xor)
|
232
|
+
|
233
|
+
return [
|
234
|
+
*target_var_decls,
|
235
|
+
*value_trim_var_decls,
|
236
|
+
*sign_var_decls,
|
237
|
+
WithinApply(
|
238
|
+
compute=[
|
239
|
+
*target_bind_ops,
|
240
|
+
*value_bind_ops,
|
241
|
+
*sign_bind_ops,
|
242
|
+
],
|
243
|
+
action=action,
|
244
|
+
),
|
245
|
+
]
|
246
|
+
|
247
|
+
|
194
248
|
def _internal_inplace_binary_operation_function_call(
|
195
249
|
internal_function_declaration: NamedParamsQuantumFunctionDeclaration,
|
196
250
|
value: Union[HandleBinding, Expression],
|
@@ -206,7 +260,7 @@ def _internal_inplace_binary_operation_function_call(
|
|
206
260
|
|
207
261
|
def _trim_superfluous_fraction_digits(
|
208
262
|
kind: str, var: QuantumSymbol, frac_digits_diff: int
|
209
|
-
) ->
|
263
|
+
) -> tuple[QuantumSymbol, list[VariableDeclarationStatement], list[BindOperation]]:
|
210
264
|
if frac_digits_diff <= 0:
|
211
265
|
return var, [], []
|
212
266
|
|
@@ -245,12 +299,12 @@ def _trim_superfluous_fraction_digits(
|
|
245
299
|
return overlap_var, split_var_declarations, [bind_op]
|
246
300
|
|
247
301
|
|
248
|
-
def _pad_with_sign_bit(kind: str, var: QuantumSymbol, size_diff: int) ->
|
302
|
+
def _pad_with_sign_bit(kind: str, var: QuantumSymbol, size_diff: int) -> tuple[
|
249
303
|
QuantumSymbol,
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
304
|
+
list[VariableDeclarationStatement],
|
305
|
+
list[QuantumStatement],
|
306
|
+
list[QuantumFunctionCall],
|
307
|
+
list[BindOperation],
|
254
308
|
]:
|
255
309
|
quantum_type = var.quantum_type
|
256
310
|
if TYPE_CHECKING:
|
@@ -290,7 +344,7 @@ def _pad_with_sign_bit(kind: str, var: QuantumSymbol, size_diff: int) -> Tuple[
|
|
290
344
|
[padding_rebind],
|
291
345
|
)
|
292
346
|
|
293
|
-
significand_var, sign_var, sign_split_bind =
|
347
|
+
significand_var, sign_var, sign_split_bind = _split_var(kind, var, 1)
|
294
348
|
padding_init_ops = _init_padding(sign_var, padding_var, size_diff)
|
295
349
|
|
296
350
|
padding_rebind = BindOperation(
|
@@ -317,7 +371,7 @@ def _pad_with_sign_bit(kind: str, var: QuantumSymbol, size_diff: int) -> Tuple[
|
|
317
371
|
|
318
372
|
def _init_padding(
|
319
373
|
sign_var: QuantumSymbol, padding_var: QuantumSymbol, size_diff: int
|
320
|
-
) ->
|
374
|
+
) -> list[QuantumFunctionCall]:
|
321
375
|
padding_init_ops = [
|
322
376
|
QuantumFunctionCall(
|
323
377
|
function=CX.func_decl.name,
|
@@ -332,7 +386,7 @@ def _init_padding(
|
|
332
386
|
|
333
387
|
def _allocate_padding(
|
334
388
|
kind: str, size_diff: int
|
335
|
-
) ->
|
389
|
+
) -> tuple[QuantumSymbol, QuantumFunctionCall]:
|
336
390
|
padding_var = QuantumSymbol(
|
337
391
|
handle=HandleBinding(name=f"{kind}_sign_padding"),
|
338
392
|
quantum_type=QuantumBitvector(
|
@@ -347,23 +401,95 @@ def _allocate_padding(
|
|
347
401
|
return padding_var, padding_allocation
|
348
402
|
|
349
403
|
|
350
|
-
def
|
351
|
-
kind: str, var: QuantumSymbol
|
352
|
-
) ->
|
353
|
-
|
354
|
-
handle=HandleBinding(name=f"{kind}
|
404
|
+
def _split_var(
|
405
|
+
kind: str, var: QuantumSymbol, right_size: int
|
406
|
+
) -> tuple[QuantumSymbol, QuantumSymbol, BindOperation]:
|
407
|
+
left_var = QuantumSymbol(
|
408
|
+
handle=HandleBinding(name=f"{kind}_left"),
|
355
409
|
quantum_type=QuantumNumeric(
|
356
|
-
size=Expression(expr=str(var.quantum_type.size_in_bits -
|
410
|
+
size=Expression(expr=str(var.quantum_type.size_in_bits - right_size)),
|
357
411
|
is_signed=Expression(expr="False"),
|
358
412
|
fraction_digits=Expression(expr="0"),
|
359
413
|
),
|
360
414
|
)
|
361
|
-
|
362
|
-
handle=HandleBinding(name=f"{kind}
|
363
|
-
quantum_type=
|
415
|
+
right_var = QuantumSymbol(
|
416
|
+
handle=HandleBinding(name=f"{kind}_right"),
|
417
|
+
quantum_type=QuantumNumeric(
|
418
|
+
size=Expression(expr=str(right_size)),
|
419
|
+
is_signed=Expression(expr="False"),
|
420
|
+
fraction_digits=Expression(expr="0"),
|
421
|
+
),
|
364
422
|
)
|
365
|
-
|
423
|
+
split_bind = BindOperation(
|
366
424
|
in_handles=[var.handle],
|
367
|
-
out_handles=[
|
425
|
+
out_handles=[left_var.handle, right_var.handle],
|
426
|
+
)
|
427
|
+
return left_var, right_var, split_bind
|
428
|
+
|
429
|
+
|
430
|
+
def _split_and_xor_sign(target_var: QuantumSymbol, value_var: QuantumSymbol) -> tuple[
|
431
|
+
Optional[QuantumSymbol],
|
432
|
+
Optional[QuantumSymbol],
|
433
|
+
list[VariableDeclarationStatement],
|
434
|
+
list[BindOperation],
|
435
|
+
list[Control],
|
436
|
+
]:
|
437
|
+
if TYPE_CHECKING:
|
438
|
+
assert isinstance(value_var.quantum_type, QuantumNumeric)
|
439
|
+
assert isinstance(target_var.quantum_type, QuantumNumeric)
|
440
|
+
size_diff = (
|
441
|
+
value_var.quantum_type.size_in_bits - target_var.quantum_type.size_in_bits
|
442
|
+
)
|
443
|
+
if not value_var.quantum_type.sign_value or size_diff >= 0:
|
444
|
+
return target_var, value_var, [], [], []
|
445
|
+
|
446
|
+
if value_var.quantum_type.size_in_bits == 1:
|
447
|
+
return None, None, [], [], [_xor_sign(target_var, value_var)]
|
448
|
+
|
449
|
+
value_rest_var, value_sign_var, value_split_bind = _split_var("value", value_var, 1)
|
450
|
+
target_left_var, target_right_var, target_split_bind = _split_var(
|
451
|
+
"target", target_var, -size_diff + 1
|
452
|
+
)
|
453
|
+
var_decls = [
|
454
|
+
VariableDeclarationStatement(
|
455
|
+
name=var.handle.name,
|
456
|
+
quantum_type=var.quantum_type,
|
457
|
+
)
|
458
|
+
for var in (value_rest_var, value_sign_var, target_left_var, target_right_var)
|
459
|
+
]
|
460
|
+
bind_ops = [value_split_bind, target_split_bind]
|
461
|
+
sign_xor = _xor_sign(target_right_var, value_sign_var)
|
462
|
+
return target_left_var, value_rest_var, var_decls, bind_ops, [sign_xor]
|
463
|
+
|
464
|
+
|
465
|
+
def _xor_sign(target_var: QuantumSymbol, value_var: QuantumSymbol) -> Control:
|
466
|
+
quantum_type = value_var.quantum_type
|
467
|
+
if TYPE_CHECKING:
|
468
|
+
assert isinstance(quantum_type, QuantumNumeric)
|
469
|
+
if quantum_type.size_in_bits != 1 or quantum_type.fraction_digits_value not in (
|
470
|
+
0,
|
471
|
+
1,
|
472
|
+
):
|
473
|
+
raise ClassiqInternalExpansionError
|
474
|
+
|
475
|
+
inner_xor = QuantumFunctionCall(
|
476
|
+
function=apply_to_all.func_decl.name,
|
477
|
+
positional_args=["X", target_var.handle],
|
478
|
+
)
|
479
|
+
inner_xor.set_func_decl(apply_to_all.func_decl)
|
480
|
+
|
481
|
+
if quantum_type.sign_value:
|
482
|
+
if quantum_type.fraction_digits_value == 1:
|
483
|
+
ctrl_value = -0.5
|
484
|
+
else:
|
485
|
+
ctrl_value = -1
|
486
|
+
else:
|
487
|
+
if quantum_type.fraction_digits_value == 1:
|
488
|
+
ctrl_value = 0.5
|
489
|
+
else:
|
490
|
+
ctrl_value = 1
|
491
|
+
|
492
|
+
return Control(
|
493
|
+
expression=Expression(expr=f"{value_var.handle} == {ctrl_value}"),
|
494
|
+
body=[inner_xor],
|
368
495
|
)
|
369
|
-
return significand_var, sign_var, sign_split_bind
|
@@ -1,4 +1,4 @@
|
|
1
|
-
from typing import TYPE_CHECKING
|
1
|
+
from typing import TYPE_CHECKING
|
2
2
|
|
3
3
|
import sympy
|
4
4
|
from sympy import sympify
|
@@ -108,8 +108,8 @@ class PhaseEmitter(ExpressionOperationEmitter[PhaseOperation]):
|
|
108
108
|
|
109
109
|
|
110
110
|
def _get_single_bit_vars_expression(
|
111
|
-
expr: sympy.Expr, vars_info:
|
112
|
-
) ->
|
111
|
+
expr: sympy.Expr, vars_info: dict[str, QuantumScalar]
|
112
|
+
) -> tuple[sympy.Expr, list[sympy.Symbol]]:
|
113
113
|
bit_vars = []
|
114
114
|
for var_name, var_info in vars_info.items():
|
115
115
|
size = var_info.size_in_bits
|
@@ -139,9 +139,9 @@ def _get_single_bit_vars_expression(
|
|
139
139
|
|
140
140
|
|
141
141
|
def _convert_ising_sympy_to_pauli_terms(
|
142
|
-
ising_expr: sympy.Expr, ordered_sympy_vars:
|
142
|
+
ising_expr: sympy.Expr, ordered_sympy_vars: list[sympy.Symbol]
|
143
143
|
) -> str:
|
144
|
-
pauli_terms:
|
144
|
+
pauli_terms: list[str] = []
|
145
145
|
coefficients = ising_expr.as_coefficients_dict(*ordered_sympy_vars)
|
146
146
|
for expr_term in ising_expr.args:
|
147
147
|
expr_vars = _get_vars(expr_term)
|
@@ -171,7 +171,7 @@ def _convert_ising_sympy_to_pauli_terms(
|
|
171
171
|
|
172
172
|
def _convert_cost_expression_to_hamiltonian(
|
173
173
|
expr: str,
|
174
|
-
vars:
|
174
|
+
vars: dict[str, QuantumScalar],
|
175
175
|
) -> Expression:
|
176
176
|
sympy_expr = sympify(expr)
|
177
177
|
single_bit_vars_expression, single_bit_vars = _get_single_bit_vars_expression(
|
@@ -1,6 +1,5 @@
|
|
1
1
|
import ast
|
2
2
|
import re
|
3
|
-
from typing import Tuple
|
4
3
|
|
5
4
|
from classiq.interface.exceptions import (
|
6
5
|
ClassiqExpansionError,
|
@@ -23,6 +22,7 @@ from classiq.interface.model.quantum_expressions.quantum_expression import (
|
|
23
22
|
from classiq.interface.model.quantum_function_call import QuantumFunctionCall
|
24
23
|
from classiq.interface.model.quantum_type import (
|
25
24
|
QuantumNumeric,
|
25
|
+
QuantumType,
|
26
26
|
)
|
27
27
|
from classiq.interface.model.variable_declaration_statement import (
|
28
28
|
VariableDeclarationStatement,
|
@@ -41,6 +41,10 @@ from classiq.model_expansions.visitors.boolean_expression_transformers import (
|
|
41
41
|
from classiq.qmod import builtins
|
42
42
|
from classiq.qmod.builtins.functions import X, allocate
|
43
43
|
|
44
|
+
HANDLE_ERROR_MESSAGE = (
|
45
|
+
"Quantum variable '{handle_str}' cannot appear on both sides of the assignment"
|
46
|
+
)
|
47
|
+
|
44
48
|
|
45
49
|
def _is_constant(expr: str) -> bool:
|
46
50
|
try:
|
@@ -129,7 +133,7 @@ class QuantumAssignmentOperationEmitter(
|
|
129
133
|
|
130
134
|
def _optimize_boolean_expression(
|
131
135
|
self, op: ArithmeticOperation, expression: Expression
|
132
|
-
) ->
|
136
|
+
) -> tuple[ArithmeticOperation, Expression, bool]:
|
133
137
|
if (
|
134
138
|
self._interpreter._is_frontend
|
135
139
|
or op.operation_kind
|
@@ -150,7 +154,7 @@ class QuantumAssignmentOperationEmitter(
|
|
150
154
|
|
151
155
|
def _adapt_boolean_inplace(
|
152
156
|
self, op: ArithmeticOperation, expression: Expression, is_bool_opt: bool
|
153
|
-
) ->
|
157
|
+
) -> tuple[ArithmeticOperation, Expression, bool]:
|
154
158
|
adapter = BooleanExpressionFuncLibAdapter(is_bool_opt)
|
155
159
|
adapted_expression = self._evaluate_expression(
|
156
160
|
Expression(expr=ast.unparse(adapter.visit(ast.parse(expression.expr))))
|
@@ -223,12 +227,28 @@ class QuantumAssignmentOperationEmitter(
|
|
223
227
|
self._interpreter.emit_statement(allocate_call)
|
224
228
|
return True
|
225
229
|
|
230
|
+
@staticmethod
|
231
|
+
def _get_updated_op_split_symbols(
|
232
|
+
op: QuantumAssignmentOperation,
|
233
|
+
symbol_mapping: dict[HandleBinding, tuple[str, QuantumType]],
|
234
|
+
) -> QuantumAssignmentOperation:
|
235
|
+
if op.result_var not in symbol_mapping:
|
236
|
+
return op
|
237
|
+
handle_str, quantum_type = symbol_mapping[op.result_var]
|
238
|
+
if handle_str in op.expression.expr:
|
239
|
+
raise ClassiqExpansionError(
|
240
|
+
HANDLE_ERROR_MESSAGE.format(handle_str=str(op.result_var))
|
241
|
+
)
|
242
|
+
new_result_handle = HandleBinding(name=handle_str)
|
243
|
+
return op.model_copy(
|
244
|
+
update=dict(result_var=new_result_handle, _result_type=quantum_type)
|
245
|
+
)
|
246
|
+
|
226
247
|
|
227
248
|
def _validate_naive_inplace_handles(qe: ArithmeticOperation) -> None:
|
228
249
|
if qe.result_var in qe.var_handles:
|
229
250
|
raise ClassiqExpansionError(
|
230
|
-
|
231
|
-
f"the ^= assignment"
|
251
|
+
HANDLE_ERROR_MESSAGE.format(handle_str=str(qe.result_var))
|
232
252
|
)
|
233
253
|
|
234
254
|
|