classiq 0.51.1__py3-none-any.whl → 0.53.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/_internals/api_wrapper.py +47 -15
- classiq/_internals/authentication/auth0.py +20 -4
- classiq/_internals/authentication/password_manager.py +16 -4
- classiq/_internals/client.py +3 -3
- classiq/_internals/host_checker.py +5 -3
- classiq/_internals/jobs.py +3 -3
- classiq/analyzer/analyzer_utilities.py +1 -1
- classiq/applications/chemistry/ground_state_problem.py +1 -1
- classiq/applications/combinatorial_helpers/pyomo_utils.py +3 -1
- classiq/applications/qnn/gradients/quantum_gradient.py +1 -1
- classiq/applications/qnn/qlayer.py +25 -6
- classiq/execution/__init__.py +5 -0
- classiq/execution/execution_session.py +43 -2
- classiq/execution/iqcc.py +63 -0
- classiq/execution/jobs.py +2 -2
- classiq/execution/qaoa.py +84 -0
- classiq/executor.py +3 -3
- classiq/interface/_version.py +1 -1
- classiq/interface/analyzer/analysis_params.py +19 -9
- classiq/interface/analyzer/cytoscape_graph.py +10 -3
- classiq/interface/analyzer/result.py +6 -5
- classiq/interface/applications/qsvm.py +13 -12
- classiq/interface/backend/backend_preferences.py +78 -105
- classiq/interface/backend/ionq/ionq_quantum_program.py +12 -19
- classiq/interface/backend/pydantic_backend.py +24 -12
- classiq/interface/backend/quantum_backend_providers.py +2 -0
- classiq/interface/chemistry/fermionic_operator.py +7 -7
- classiq/interface/chemistry/ground_state_problem.py +23 -18
- classiq/interface/chemistry/molecule.py +10 -5
- classiq/interface/chemistry/operator.py +71 -44
- classiq/interface/combinatorial_optimization/mht_qaoa_input.py +2 -1
- classiq/interface/debug_info/debug_info.py +3 -4
- classiq/interface/exceptions.py +3 -1
- classiq/interface/execution/iqcc.py +19 -0
- classiq/interface/execution/jobs.py +10 -10
- classiq/interface/executor/aws_execution_cost.py +37 -20
- classiq/interface/executor/execution_preferences.py +1 -2
- classiq/interface/executor/execution_request.py +2 -2
- classiq/interface/executor/execution_result.py +4 -2
- classiq/interface/executor/iqae_result.py +1 -1
- classiq/interface/executor/optimizer_preferences.py +14 -10
- classiq/interface/executor/quantum_code.py +21 -16
- classiq/interface/executor/register_initialization.py +10 -10
- classiq/interface/executor/result.py +31 -17
- classiq/interface/executor/vqe_result.py +1 -1
- classiq/interface/finance/function_input.py +27 -18
- classiq/interface/finance/log_normal_model_input.py +2 -2
- classiq/interface/finance/model_input.py +3 -2
- classiq/interface/generator/amplitude_loading.py +8 -6
- classiq/interface/generator/arith/argument_utils.py +24 -0
- classiq/interface/generator/arith/arithmetic.py +5 -3
- classiq/interface/generator/arith/arithmetic_expression_abc.py +36 -14
- classiq/interface/generator/arith/arithmetic_operations.py +6 -3
- classiq/interface/generator/arith/binary_ops.py +88 -63
- classiq/interface/generator/arith/extremum_operations.py +22 -13
- classiq/interface/generator/arith/logical_ops.py +6 -4
- classiq/interface/generator/arith/number_utils.py +3 -3
- classiq/interface/generator/arith/register_user_input.py +32 -17
- classiq/interface/generator/arith/unary_ops.py +5 -4
- classiq/interface/generator/chemistry_function_params.py +2 -1
- classiq/interface/generator/circuit_code/circuit_code.py +2 -1
- classiq/interface/generator/commuting_pauli_exponentiation.py +6 -5
- classiq/interface/generator/complex_type.py +14 -18
- classiq/interface/generator/control_state.py +32 -26
- classiq/interface/generator/expressions/expression.py +6 -5
- classiq/interface/generator/function_params.py +22 -39
- classiq/interface/generator/functions/classical_function_declaration.py +1 -1
- classiq/interface/generator/functions/classical_type.py +32 -23
- classiq/interface/generator/functions/concrete_types.py +8 -7
- classiq/interface/generator/functions/function_declaration.py +4 -5
- classiq/interface/generator/functions/type_name.py +5 -4
- classiq/interface/generator/generated_circuit_data.py +9 -6
- classiq/interface/generator/grover_diffuser.py +26 -18
- classiq/interface/generator/grover_operator.py +32 -22
- classiq/interface/generator/hamiltonian_evolution/exponentiation.py +3 -4
- classiq/interface/generator/hamiltonian_evolution/qdrift.py +4 -4
- classiq/interface/generator/hamiltonian_evolution/suzuki_trotter.py +8 -7
- classiq/interface/generator/hardware/hardware_data.py +27 -26
- classiq/interface/generator/hardware_efficient_ansatz.py +11 -6
- classiq/interface/generator/hartree_fock.py +2 -1
- classiq/interface/generator/identity.py +7 -2
- classiq/interface/generator/linear_pauli_rotations.py +27 -14
- classiq/interface/generator/mcu.py +15 -12
- classiq/interface/generator/mcx.py +18 -10
- classiq/interface/generator/model/constraints.py +4 -2
- classiq/interface/generator/model/model.py +2 -1
- classiq/interface/generator/model/preferences/preferences.py +30 -32
- classiq/interface/generator/oracles/custom_oracle.py +13 -10
- classiq/interface/generator/piecewise_linear_amplitude_loading.py +37 -21
- classiq/interface/generator/qpe.py +38 -26
- classiq/interface/generator/qsvm.py +4 -4
- classiq/interface/generator/quantum_function_call.py +57 -44
- classiq/interface/generator/quantum_program.py +8 -6
- classiq/interface/generator/range_types.py +10 -11
- classiq/interface/generator/standard_gates/controlled_standard_gates.py +9 -5
- classiq/interface/generator/standard_gates/standard_angle_metaclass.py +2 -6
- classiq/interface/generator/standard_gates/u_gate.py +7 -10
- classiq/interface/generator/state_preparation/computational_basis_state_preparation.py +2 -1
- classiq/interface/generator/state_preparation/distributions.py +12 -12
- classiq/interface/generator/state_preparation/state_preparation.py +22 -16
- classiq/interface/generator/types/enum_declaration.py +2 -1
- classiq/interface/generator/ucc.py +2 -1
- classiq/interface/generator/unitary_gate.py +2 -1
- classiq/interface/generator/user_defined_function_params.py +3 -0
- classiq/interface/generator/visitor.py +1 -1
- classiq/interface/hardware.py +18 -3
- classiq/interface/helpers/custom_pydantic_types.py +38 -47
- classiq/interface/helpers/dotdict.py +18 -0
- classiq/interface/helpers/pydantic_model_helpers.py +3 -2
- classiq/interface/helpers/versioned_model.py +1 -4
- classiq/interface/ide/ide_data.py +5 -5
- classiq/interface/ide/visual_model.py +18 -5
- classiq/interface/interface_version.py +1 -1
- classiq/interface/jobs.py +12 -22
- classiq/interface/model/bind_operation.py +2 -1
- classiq/interface/model/classical_parameter_declaration.py +10 -4
- classiq/interface/model/handle_binding.py +20 -24
- classiq/interface/model/inplace_binary_operation.py +16 -9
- classiq/interface/model/model.py +21 -11
- classiq/interface/model/native_function_definition.py +10 -0
- classiq/interface/model/port_declaration.py +10 -7
- classiq/interface/model/quantum_expressions/arithmetic_operation.py +6 -4
- classiq/interface/model/quantum_function_declaration.py +22 -11
- classiq/interface/model/quantum_statement.py +6 -7
- classiq/interface/model/quantum_type.py +22 -19
- classiq/interface/model/statement_block.py +9 -9
- classiq/interface/server/global_versions.py +4 -5
- classiq/interface/server/routes.py +8 -0
- classiq/model_expansions/evaluators/parameter_types.py +3 -3
- classiq/model_expansions/expression_renamer.py +1 -1
- classiq/model_expansions/quantum_operations/control.py +11 -12
- classiq/model_expansions/quantum_operations/emitter.py +22 -0
- classiq/model_expansions/quantum_operations/expression_operation.py +2 -20
- classiq/model_expansions/quantum_operations/inplace_binary_operation.py +42 -12
- classiq/model_expansions/quantum_operations/invert.py +1 -1
- classiq/model_expansions/quantum_operations/phase.py +4 -5
- classiq/model_expansions/quantum_operations/power.py +1 -1
- classiq/model_expansions/quantum_operations/quantum_assignment_operation.py +50 -9
- classiq/model_expansions/quantum_operations/variable_decleration.py +2 -2
- classiq/model_expansions/quantum_operations/within_apply.py +1 -1
- classiq/qmod/__init__.py +2 -0
- classiq/qmod/builtins/__init__.py +1 -3
- classiq/qmod/builtins/functions/__init__.py +9 -0
- classiq/qmod/builtins/functions/arithmetic.py +10 -0
- classiq/qmod/builtins/functions/standard_gates.py +14 -14
- classiq/qmod/builtins/functions/variational.py +37 -0
- classiq/qmod/create_model_function.py +16 -6
- classiq/qmod/qmod_parameter.py +3 -1
- classiq/qmod/quantum_expandable.py +43 -10
- classiq/qmod/quantum_function.py +24 -2
- classiq/qmod/semantics/static_semantics_visitor.py +3 -1
- classiq/qmod/synthesize_separately.py +16 -0
- classiq/qmod/type_attribute_remover.py +1 -1
- classiq/qmod/write_qmod.py +2 -4
- classiq/synthesis.py +11 -13
- {classiq-0.51.1.dist-info → classiq-0.53.0.dist-info}/METADATA +3 -2
- {classiq-0.51.1.dist-info → classiq-0.53.0.dist-info}/RECORD +158 -152
- {classiq-0.51.1.dist-info → classiq-0.53.0.dist-info}/WHEEL +0 -0
@@ -46,12 +46,12 @@ ConcreteQuantumStatement = Annotated[
|
|
46
46
|
|
47
47
|
StatementBlock = List[ConcreteQuantumStatement]
|
48
48
|
|
49
|
-
Control.
|
50
|
-
QuantumLambdaFunction.
|
51
|
-
Repeat.
|
52
|
-
Power.
|
53
|
-
Invert.
|
54
|
-
WithinApply.
|
55
|
-
ClassicalIf.
|
56
|
-
NativeFunctionDefinition.
|
57
|
-
PhaseOperation.
|
49
|
+
Control.model_rebuild()
|
50
|
+
QuantumLambdaFunction.model_rebuild()
|
51
|
+
Repeat.model_rebuild()
|
52
|
+
Power.model_rebuild()
|
53
|
+
Invert.model_rebuild()
|
54
|
+
WithinApply.model_rebuild()
|
55
|
+
ClassicalIf.model_rebuild()
|
56
|
+
NativeFunctionDefinition.model_rebuild()
|
57
|
+
PhaseOperation.model_rebuild()
|
@@ -1,15 +1,14 @@
|
|
1
1
|
from datetime import date
|
2
2
|
from typing import Any, Dict
|
3
3
|
|
4
|
-
import pydantic
|
5
4
|
from pydantic import BaseModel
|
6
5
|
|
7
6
|
|
8
7
|
class DeprecationInfo(BaseModel):
|
9
|
-
deprecation_date: date
|
10
|
-
removal_date: date
|
8
|
+
deprecation_date: date
|
9
|
+
removal_date: date
|
11
10
|
|
12
11
|
|
13
12
|
class GlobalVersions(BaseModel):
|
14
|
-
deprecated: Dict[str, DeprecationInfo]
|
15
|
-
deployed: Dict[str, Any]
|
13
|
+
deprecated: Dict[str, DeprecationInfo]
|
14
|
+
deployed: Dict[str, Any]
|
@@ -2,6 +2,9 @@ ANALYZER_PREFIX = "/analyzer"
|
|
2
2
|
CHEMISTRY_PREFIX = "/chemistry"
|
3
3
|
EXECUTION_PREFIX = "/execution"
|
4
4
|
CONVERSION_PREFIX = "/conversion"
|
5
|
+
PROVIDERS_PREFIX = "/providers"
|
6
|
+
|
7
|
+
IQCC_PREFIX = PROVIDERS_PREFIX + "/iqcc"
|
5
8
|
|
6
9
|
EXECUTION_NON_VERSIONED_PREFIX = "/execution/v1"
|
7
10
|
SYNTHESIS_NON_VERSIONED_PREFIX = "/synthesis/v1"
|
@@ -71,3 +74,8 @@ CONVERSION_GENERATED_CIRCUIT_TO_EXECUTION_INPUT_FULL = (
|
|
71
74
|
)
|
72
75
|
|
73
76
|
STATIC_SEMANTICS_VALIDATION_PATH = "/validate_static_semantics"
|
77
|
+
|
78
|
+
IQCC_INIT_AUTH_SUFFIX = "/init_auth"
|
79
|
+
IQCC_INIT_AUTH_FULL_PATH = IQCC_PREFIX + IQCC_INIT_AUTH_SUFFIX
|
80
|
+
IQCC_PROBE_AUTH_SUFFIX = "/probe_auth"
|
81
|
+
IQCC_PROBE_AUTH_FULL_PATH = IQCC_PREFIX + IQCC_PROBE_AUTH_SUFFIX
|
@@ -118,7 +118,7 @@ def _update_operand_signature_environment(
|
|
118
118
|
def _cast(
|
119
119
|
quantum_type: QuantumType, quantum_symbol: QuantumSymbol, param_name: str
|
120
120
|
) -> QuantumSymbol:
|
121
|
-
updated_quantum_type = quantum_type.
|
121
|
+
updated_quantum_type = quantum_type.model_copy()
|
122
122
|
_inject_quantum_arg_info_to_type(updated_quantum_type, quantum_symbol, param_name)
|
123
123
|
return QuantumSymbol(
|
124
124
|
handle=quantum_symbol.handle, quantum_type=updated_quantum_type
|
@@ -132,13 +132,13 @@ def _evaluate_type_from_arg(
|
|
132
132
|
return parameter
|
133
133
|
|
134
134
|
updated_quantum_type: QuantumType = evaluate_type_in_quantum_symbol(
|
135
|
-
parameter.quantum_type.
|
135
|
+
parameter.quantum_type.model_copy(), inner_scope, parameter.name
|
136
136
|
)
|
137
137
|
if parameter.direction != PortDeclarationDirection.Output:
|
138
138
|
updated_quantum_type = _inject_quantum_arg_info_to_type(
|
139
139
|
updated_quantum_type, argument.as_type(QuantumSymbol), parameter.name
|
140
140
|
)
|
141
|
-
return parameter.
|
141
|
+
return parameter.model_copy(update={"quantum_type": updated_quantum_type})
|
142
142
|
|
143
143
|
|
144
144
|
def evaluate_type_in_quantum_symbol(
|
@@ -30,7 +30,7 @@ class ExpressionRenamer(Transformer):
|
|
30
30
|
update_dict = dict(
|
31
31
|
positional_args=[self.visit(arg) for arg in node.positional_args],
|
32
32
|
)
|
33
|
-
return node.
|
33
|
+
return node.model_copy(update=update_dict)
|
34
34
|
|
35
35
|
def visit_Expression(self, expression: Expression) -> Expression:
|
36
36
|
parsed_expr = ast.parse(expression.expr)
|
@@ -23,7 +23,6 @@ from classiq.interface.model.quantum_expressions.arithmetic_operation import (
|
|
23
23
|
ArithmeticOperation,
|
24
24
|
ArithmeticOperationKind,
|
25
25
|
)
|
26
|
-
from classiq.interface.model.quantum_function_call import QuantumFunctionCall
|
27
26
|
from classiq.interface.model.quantum_type import QuantumBit, QuantumBitvector
|
28
27
|
from classiq.interface.model.statement_block import ConcreteQuantumStatement
|
29
28
|
from classiq.interface.model.variable_declaration_statement import (
|
@@ -43,7 +42,6 @@ from classiq.model_expansions.quantum_operations.expression_operation import (
|
|
43
42
|
ExpressionOperationEmitter,
|
44
43
|
)
|
45
44
|
from classiq.model_expansions.scope import Scope
|
46
|
-
from classiq.qmod.builtins.functions import inplace_prepare_int
|
47
45
|
|
48
46
|
ARRAY_CAST_SUFFIX = HANDLE_ID_SEPARATOR + "array_cast"
|
49
47
|
|
@@ -51,7 +49,7 @@ ARRAY_CAST_SUFFIX = HANDLE_ID_SEPARATOR + "array_cast"
|
|
51
49
|
class ControlEmitter(ExpressionOperationEmitter[Control]):
|
52
50
|
def emit(self, control: Control, /) -> None:
|
53
51
|
condition = self._evaluate_op_expression(control)
|
54
|
-
control = control.
|
52
|
+
control = control.model_copy(update=dict(expression=condition))
|
55
53
|
|
56
54
|
arrays_with_subscript = self._get_symbols_to_split(condition)
|
57
55
|
if len(arrays_with_subscript) > 0:
|
@@ -76,7 +74,7 @@ class ControlEmitter(ExpressionOperationEmitter[Control]):
|
|
76
74
|
def _emit_propagated(self, control: Control) -> None:
|
77
75
|
if control.is_generative():
|
78
76
|
context = self._register_generative_context(control, CONTROL_OPERATOR_NAME)
|
79
|
-
control = control.
|
77
|
+
control = control.model_copy(update={"body": context.statements("body")})
|
80
78
|
|
81
79
|
if self._should_wrap_control(control):
|
82
80
|
self._emit_wrapped(control)
|
@@ -106,7 +104,7 @@ class ControlEmitter(ExpressionOperationEmitter[Control]):
|
|
106
104
|
)
|
107
105
|
self._update_control_state(control)
|
108
106
|
self._builder.emit_statement(
|
109
|
-
control.
|
107
|
+
control.model_copy(update=dict(body=context.statements("body")))
|
110
108
|
)
|
111
109
|
|
112
110
|
def _emit_wrapped(self, control: Control) -> None:
|
@@ -119,7 +117,7 @@ class ControlEmitter(ExpressionOperationEmitter[Control]):
|
|
119
117
|
)
|
120
118
|
self._update_control_state(control)
|
121
119
|
self._builder.emit_statement(
|
122
|
-
control.
|
120
|
+
control.model_copy(update=dict(body=[wrapping_function]))
|
123
121
|
)
|
124
122
|
|
125
123
|
@staticmethod
|
@@ -157,7 +155,7 @@ class ControlEmitter(ExpressionOperationEmitter[Control]):
|
|
157
155
|
self, control: Control, handle_name: str
|
158
156
|
) -> Control:
|
159
157
|
handle_expr = self._interpreter.evaluate(Expression(expr=handle_name)).emit()
|
160
|
-
return control.
|
158
|
+
return control.model_copy(update=dict(expression=handle_expr))
|
161
159
|
|
162
160
|
def _emit_with_x_gates(
|
163
161
|
self, control: Control, ctrl: QmodSizedProxy, ctrl_state: str
|
@@ -166,12 +164,13 @@ class ControlEmitter(ExpressionOperationEmitter[Control]):
|
|
166
164
|
|
167
165
|
x_gate_value = self._get_x_gate_value(ctrl_state)
|
168
166
|
if x_gate_value != 0:
|
169
|
-
|
170
|
-
|
171
|
-
|
167
|
+
compute_op.append(
|
168
|
+
ArithmeticOperation(
|
169
|
+
result_var=ctrl.handle,
|
170
|
+
expression=Expression(expr=str(x_gate_value)),
|
171
|
+
operation_kind=ArithmeticOperationKind.InplaceXor,
|
172
|
+
)
|
172
173
|
)
|
173
|
-
prepare_int_call.set_func_decl(inplace_prepare_int.func_decl)
|
174
|
-
compute_op.append(prepare_int_call)
|
175
174
|
|
176
175
|
if isinstance(ctrl, QmodQNumProxy):
|
177
176
|
# Canonical control does not accept QNum, so we have to cast it
|
@@ -11,7 +11,13 @@ from typing import (
|
|
11
11
|
cast,
|
12
12
|
)
|
13
13
|
|
14
|
+
import sympy
|
15
|
+
|
14
16
|
from classiq.interface.debug_info.debug_info import FunctionDebugInfo
|
17
|
+
from classiq.interface.generator.expressions.evaluated_expression import (
|
18
|
+
EvaluatedExpression,
|
19
|
+
)
|
20
|
+
from classiq.interface.generator.expressions.expression import Expression
|
15
21
|
from classiq.interface.ide.visual_model import OperationLevel
|
16
22
|
from classiq.interface.model.classical_parameter_declaration import (
|
17
23
|
ClassicalParameterDeclaration,
|
@@ -47,6 +53,9 @@ from classiq.model_expansions.function_builder import (
|
|
47
53
|
)
|
48
54
|
from classiq.model_expansions.generative_functions import emit_operands_as_declarative
|
49
55
|
from classiq.model_expansions.scope import Evaluated, QuantumSymbol, Scope
|
56
|
+
from classiq.model_expansions.sympy_conversion.sympy_to_python import (
|
57
|
+
translate_sympy_quantum_expression,
|
58
|
+
)
|
50
59
|
from classiq.model_expansions.utils.counted_name_allocator import CountedNameAllocator
|
51
60
|
from classiq.qmod.builtins.functions import allocate, free
|
52
61
|
from classiq.qmod.quantum_function import GenerativeQFunc
|
@@ -274,3 +283,16 @@ class Emitter(Generic[QuantumStatementT]):
|
|
274
283
|
context = self._interpreter._expand_operation(gen_closure)
|
275
284
|
self._generative_contexts[context_name] = context
|
276
285
|
return context
|
286
|
+
|
287
|
+
def _evaluate_expression(self, expression: Expression) -> Expression:
|
288
|
+
evaluated_expression = self._interpreter.evaluate(expression)
|
289
|
+
if isinstance(evaluated_expression.value, sympy.Basic):
|
290
|
+
new_expression = Expression(
|
291
|
+
expr=translate_sympy_quantum_expression(evaluated_expression.value)
|
292
|
+
)
|
293
|
+
else:
|
294
|
+
new_expression = Expression(expr=str(evaluated_expression.value))
|
295
|
+
new_expression._evaluated_expr = EvaluatedExpression(
|
296
|
+
value=evaluated_expression.value
|
297
|
+
)
|
298
|
+
return new_expression
|
@@ -3,8 +3,6 @@ from abc import abstractmethod
|
|
3
3
|
from itertools import chain
|
4
4
|
from typing import TYPE_CHECKING, Dict, List, Tuple, TypeVar
|
5
5
|
|
6
|
-
import sympy
|
7
|
-
|
8
6
|
from classiq.interface.exceptions import (
|
9
7
|
ClassiqExpansionError,
|
10
8
|
ClassiqInternalExpansionError,
|
@@ -36,9 +34,6 @@ from classiq.interface.model.within_apply_operation import WithinApply
|
|
36
34
|
|
37
35
|
from classiq.model_expansions.quantum_operations.emitter import Emitter
|
38
36
|
from classiq.model_expansions.scope import QuantumSymbol
|
39
|
-
from classiq.model_expansions.sympy_conversion.sympy_to_python import (
|
40
|
-
translate_sympy_quantum_expression,
|
41
|
-
)
|
42
37
|
from classiq.model_expansions.visitors.variable_references import VarRefCollector
|
43
38
|
|
44
39
|
ExpressionOperationT = TypeVar("ExpressionOperationT", bound=QuantumExpressionOperation)
|
@@ -74,7 +69,7 @@ class ExpressionOperationEmitter(Emitter[ExpressionOperationT]):
|
|
74
69
|
},
|
75
70
|
expression,
|
76
71
|
)
|
77
|
-
new_op = op.
|
72
|
+
new_op = op.model_copy(update=dict(expression=new_expression))
|
78
73
|
|
79
74
|
self._interpreter.emit_statement(
|
80
75
|
WithinApply(
|
@@ -194,23 +189,10 @@ class ExpressionOperationEmitter(Emitter[ExpressionOperationT]):
|
|
194
189
|
def _evaluate_op_expression(self, op: ExpressionOperationT) -> Expression:
|
195
190
|
return self._evaluate_expression(op.expression)
|
196
191
|
|
197
|
-
def _evaluate_expression(self, expression: Expression) -> Expression:
|
198
|
-
evaluated_expression = self._interpreter.evaluate(expression)
|
199
|
-
if isinstance(evaluated_expression.value, sympy.Basic):
|
200
|
-
new_expression = Expression(
|
201
|
-
expr=translate_sympy_quantum_expression(evaluated_expression.value)
|
202
|
-
)
|
203
|
-
else:
|
204
|
-
new_expression = Expression(expr=str(evaluated_expression.value))
|
205
|
-
new_expression._evaluated_expr = EvaluatedExpression(
|
206
|
-
value=evaluated_expression.value
|
207
|
-
)
|
208
|
-
return new_expression
|
209
|
-
|
210
192
|
def _evaluate_types_in_expression(
|
211
193
|
self, op: ExpressionOperationT, expression: Expression
|
212
194
|
) -> ExpressionOperationT:
|
213
|
-
op_with_evaluated_types = op.
|
195
|
+
op_with_evaluated_types = op.model_copy(update={"expression": expression})
|
214
196
|
vrc = VarRefCollector()
|
215
197
|
vrc.visit(ast.parse(op_with_evaluated_types.expression.expr))
|
216
198
|
handles = vrc.var_handles
|
@@ -1,4 +1,4 @@
|
|
1
|
-
from typing import TYPE_CHECKING, List, Tuple
|
1
|
+
from typing import TYPE_CHECKING, List, Tuple, Union
|
2
2
|
|
3
3
|
from classiq.interface.generator.expressions.expression import Expression
|
4
4
|
from classiq.interface.generator.functions.port_declaration import (
|
@@ -35,20 +35,37 @@ from classiq.model_expansions.evaluators.quantum_type_utils import (
|
|
35
35
|
)
|
36
36
|
from classiq.model_expansions.quantum_operations.emitter import Emitter
|
37
37
|
from classiq.model_expansions.scope import QuantumSymbol, Scope
|
38
|
-
from classiq.qmod.builtins.functions import
|
38
|
+
from classiq.qmod.builtins.functions import (
|
39
|
+
CX,
|
40
|
+
allocate,
|
41
|
+
integer_xor,
|
42
|
+
modular_add,
|
43
|
+
modular_add_constant,
|
44
|
+
real_xor_constant,
|
45
|
+
)
|
39
46
|
|
40
47
|
|
41
48
|
def _binary_function_declaration(
|
42
|
-
op: BinaryOperation,
|
49
|
+
op: BinaryOperation, constant: bool
|
43
50
|
) -> NamedParamsQuantumFunctionDeclaration:
|
44
51
|
return {
|
45
|
-
|
46
|
-
|
47
|
-
|
52
|
+
False: {
|
53
|
+
BinaryOperation.Addition: modular_add.func_decl,
|
54
|
+
BinaryOperation.Xor: integer_xor.func_decl,
|
55
|
+
},
|
56
|
+
True: {
|
57
|
+
BinaryOperation.Addition: modular_add_constant.func_decl,
|
58
|
+
BinaryOperation.Xor: real_xor_constant.func_decl,
|
59
|
+
},
|
60
|
+
}[constant][op]
|
48
61
|
|
49
62
|
|
50
63
|
class InplaceBinaryOperationEmitter(Emitter[InplaceBinaryOperation]):
|
51
64
|
def emit(self, op: InplaceBinaryOperation, /) -> None:
|
65
|
+
if isinstance(op.value, Expression):
|
66
|
+
self._emit_constant_operation(op)
|
67
|
+
return
|
68
|
+
|
52
69
|
value_var = self._interpreter.evaluate(op.value).as_type(QuantumSymbol)
|
53
70
|
target_var = self._interpreter.evaluate(op.target).as_type(QuantumSymbol)
|
54
71
|
value_var, target_var = evaluate_types_in_quantum_symbols(
|
@@ -95,7 +112,7 @@ class InplaceBinaryOperationEmitter(Emitter[InplaceBinaryOperation]):
|
|
95
112
|
value_var=value_var,
|
96
113
|
target_var=target_var,
|
97
114
|
internal_function_declaration=_binary_function_declaration(
|
98
|
-
op.operation
|
115
|
+
op.operation, constant=False
|
99
116
|
),
|
100
117
|
),
|
101
118
|
scope=Scope(parent=self._current_scope),
|
@@ -105,6 +122,18 @@ class InplaceBinaryOperationEmitter(Emitter[InplaceBinaryOperation]):
|
|
105
122
|
inplace_binary_op_function, [op.value, op.target]
|
106
123
|
)
|
107
124
|
|
125
|
+
def _emit_constant_operation(self, op: InplaceBinaryOperation) -> None:
|
126
|
+
if TYPE_CHECKING:
|
127
|
+
assert isinstance(op.value, Expression)
|
128
|
+
value = self._evaluate_expression(op.value)
|
129
|
+
self._interpreter.emit(
|
130
|
+
_internal_inplace_binary_operation_function_call(
|
131
|
+
_binary_function_declaration(op.operation, constant=True),
|
132
|
+
value,
|
133
|
+
op.target,
|
134
|
+
)
|
135
|
+
)
|
136
|
+
|
108
137
|
|
109
138
|
def _build_inplace_binary_operation(
|
110
139
|
value_var: QuantumSymbol,
|
@@ -119,9 +148,6 @@ def _build_inplace_binary_operation(
|
|
119
148
|
value_var.quantum_type.fraction_digits_value
|
120
149
|
- target_var.quantum_type.fraction_digits_value
|
121
150
|
)
|
122
|
-
size_diff = (
|
123
|
-
value_var.quantum_type.size_in_bits - target_var.quantum_type.size_in_bits
|
124
|
-
)
|
125
151
|
|
126
152
|
target_overlap_var, target_var_decls, target_bind_ops = (
|
127
153
|
_trim_superfluous_fraction_digits("target", target_var, -frac_digits_diff)
|
@@ -129,6 +155,10 @@ def _build_inplace_binary_operation(
|
|
129
155
|
value_overlap_var, value_trim_var_decls, value_bind_ops = (
|
130
156
|
_trim_superfluous_fraction_digits("value", value_var, frac_digits_diff)
|
131
157
|
)
|
158
|
+
size_diff = (
|
159
|
+
value_overlap_var.quantum_type.size_in_bits
|
160
|
+
- target_overlap_var.quantum_type.size_in_bits
|
161
|
+
)
|
132
162
|
(
|
133
163
|
value_padded_var,
|
134
164
|
value_pad_var_decls,
|
@@ -164,12 +194,12 @@ def _build_inplace_binary_operation(
|
|
164
194
|
|
165
195
|
def _internal_inplace_binary_operation_function_call(
|
166
196
|
internal_function_declaration: NamedParamsQuantumFunctionDeclaration,
|
167
|
-
|
197
|
+
value: Union[HandleBinding, Expression],
|
168
198
|
target_var: HandleBinding,
|
169
199
|
) -> QuantumFunctionCall:
|
170
200
|
internal_function_call = QuantumFunctionCall(
|
171
201
|
function=internal_function_declaration.name,
|
172
|
-
positional_args=[
|
202
|
+
positional_args=[value, target_var],
|
173
203
|
)
|
174
204
|
internal_function_call.set_func_decl(internal_function_declaration)
|
175
205
|
return internal_function_call
|
@@ -16,7 +16,7 @@ class InvertEmitter(Emitter[Invert]):
|
|
16
16
|
def _emit_propagated(self, invert: Invert, /) -> None:
|
17
17
|
if invert.is_generative():
|
18
18
|
context = self._register_generative_context(invert, INVERT_OPERATOR_NAME)
|
19
|
-
invert = invert.
|
19
|
+
invert = invert.model_copy(update={"body": context.statements("body")})
|
20
20
|
|
21
21
|
if self._should_wrap(invert.body):
|
22
22
|
self._emit_wrapped(invert)
|
@@ -35,19 +35,18 @@ from classiq.qmod.semantics.error_manager import ErrorManager
|
|
35
35
|
class PhaseEmitter(ExpressionOperationEmitter[PhaseOperation]):
|
36
36
|
def _negate_expression(self, expression: Expression, /) -> Expression:
|
37
37
|
return self._evaluate_expression(
|
38
|
-
|
39
|
-
expression.copy(update=dict(expr=f"-({expression.expr})"))
|
38
|
+
expression.model_copy(update=dict(expr=f"-({expression.expr})"))
|
40
39
|
)
|
41
40
|
|
42
41
|
def emit(self, phase_op: PhaseOperation, /) -> None:
|
43
42
|
phase_expression = self._evaluate_op_expression(phase_op)
|
44
|
-
phase_op = phase_op.
|
43
|
+
phase_op = phase_op.model_copy(update=dict(expression=phase_expression))
|
45
44
|
arrays_with_subscript = self._get_symbols_to_split(phase_op.expression)
|
46
45
|
if len(arrays_with_subscript) > 0:
|
47
46
|
self._emit_with_split(phase_op, phase_op.expression, arrays_with_subscript)
|
48
47
|
return
|
49
|
-
|
50
|
-
phase_op = phase_op.
|
48
|
+
|
49
|
+
phase_op = phase_op.model_copy(
|
51
50
|
update=dict(expression=self._negate_expression(phase_op.expression))
|
52
51
|
)
|
53
52
|
phase_op = self._evaluate_types_in_expression(phase_op, phase_op.expression)
|
@@ -27,7 +27,7 @@ class PowerEmitter(Emitter[Power]):
|
|
27
27
|
def _emit_propagated(self, power: Power) -> None:
|
28
28
|
if power.is_generative():
|
29
29
|
context = self._register_generative_context(power, POWER_OPERATOR_NAME)
|
30
|
-
power = power.
|
30
|
+
power = power.model_copy(update={"body": context.statements("body")})
|
31
31
|
|
32
32
|
self._power = power
|
33
33
|
self._power_value = self._get_power_value()
|
@@ -1,7 +1,11 @@
|
|
1
1
|
import ast
|
2
|
+
import re
|
2
3
|
from typing import Tuple
|
3
4
|
|
4
|
-
from classiq.interface.exceptions import
|
5
|
+
from classiq.interface.exceptions import (
|
6
|
+
ClassiqExpansionError,
|
7
|
+
ClassiqInternalExpansionError,
|
8
|
+
)
|
5
9
|
from classiq.interface.generator.compiler_keywords import INPLACE_ARITH_AUX_VAR_PREFIX
|
6
10
|
from classiq.interface.generator.expressions.expression import Expression
|
7
11
|
from classiq.interface.model.handle_binding import HandleBinding
|
@@ -38,13 +42,22 @@ from classiq.qmod import builtins
|
|
38
42
|
from classiq.qmod.builtins.functions import X, allocate
|
39
43
|
|
40
44
|
|
41
|
-
def
|
45
|
+
def _is_constant(expr: str) -> bool:
|
42
46
|
try:
|
43
|
-
|
47
|
+
float(expr)
|
48
|
+
return True
|
44
49
|
except ValueError:
|
45
50
|
return False
|
46
51
|
|
47
52
|
|
53
|
+
def _is_zero(expr: str) -> bool:
|
54
|
+
return _is_constant(expr) and float(expr) == 0
|
55
|
+
|
56
|
+
|
57
|
+
def _is_variable(expr: str) -> bool:
|
58
|
+
return re.fullmatch("[a-zA-Z_][a-zA-Z0-9_]*", expr) is not None
|
59
|
+
|
60
|
+
|
48
61
|
class QuantumAssignmentOperationEmitter(
|
49
62
|
ExpressionOperationEmitter[QuantumAssignmentOperation]
|
50
63
|
):
|
@@ -86,6 +99,7 @@ class QuantumAssignmentOperationEmitter(
|
|
86
99
|
or op.result_type.size_in_bits > 1
|
87
100
|
or not _is_res_boolean(op)
|
88
101
|
or target.quantum_type.size_in_bits > 1
|
102
|
+
or _is_constant(expression.expr)
|
89
103
|
):
|
90
104
|
_validate_naive_inplace_handles(op)
|
91
105
|
self._build_naive_inplace(op, expression)
|
@@ -131,7 +145,7 @@ class QuantumAssignmentOperationEmitter(
|
|
131
145
|
expr=ast.unparse(optimizer.visit(ast.parse(expression.expr)))
|
132
146
|
)
|
133
147
|
optimized_expression = self._evaluate_expression(optimized_expression)
|
134
|
-
optimized_op = op.
|
148
|
+
optimized_op = op.model_copy(update=dict(expression=optimized_expression))
|
135
149
|
return optimized_op, optimized_expression, optimizer.is_convertible
|
136
150
|
|
137
151
|
def _adapt_boolean_inplace(
|
@@ -141,12 +155,43 @@ class QuantumAssignmentOperationEmitter(
|
|
141
155
|
adapted_expression = self._evaluate_expression(
|
142
156
|
Expression(expr=ast.unparse(adapter.visit(ast.parse(expression.expr))))
|
143
157
|
)
|
144
|
-
adapted_op = op.
|
158
|
+
adapted_op = op.model_copy(update=dict(expression=adapted_expression))
|
145
159
|
return adapted_op, adapted_expression, adapter.to_invert
|
146
160
|
|
147
161
|
def _build_naive_inplace(
|
148
162
|
self, qe: ArithmeticOperation, new_expression: Expression
|
149
163
|
) -> None:
|
164
|
+
if qe.operation_kind == ArithmeticOperationKind.InplaceXor:
|
165
|
+
op = BinaryOperation.Xor
|
166
|
+
elif qe.operation_kind == ArithmeticOperationKind.InplaceAdd:
|
167
|
+
op = BinaryOperation.Addition
|
168
|
+
else:
|
169
|
+
raise ClassiqInternalExpansionError(
|
170
|
+
f"Unrecognized operation kind {qe.operation_kind!r}"
|
171
|
+
)
|
172
|
+
|
173
|
+
if _is_constant(new_expression.expr):
|
174
|
+
self._interpreter.emit_statement(
|
175
|
+
InplaceBinaryOperation(
|
176
|
+
operation=op,
|
177
|
+
target=qe.result_var,
|
178
|
+
value=new_expression,
|
179
|
+
)
|
180
|
+
)
|
181
|
+
return
|
182
|
+
|
183
|
+
if _is_variable(new_expression.expr):
|
184
|
+
value_var = self._interpreter.evaluate(new_expression.expr).value
|
185
|
+
if isinstance(value_var, QuantumSymbol):
|
186
|
+
self._interpreter.emit_statement(
|
187
|
+
InplaceBinaryOperation(
|
188
|
+
operation=op,
|
189
|
+
target=qe.result_var,
|
190
|
+
value=value_var.handle,
|
191
|
+
)
|
192
|
+
)
|
193
|
+
return
|
194
|
+
|
150
195
|
aux_var = self._counted_name_allocator.allocate(INPLACE_ARITH_AUX_VAR_PREFIX)
|
151
196
|
self._interpreter.emit_statement(
|
152
197
|
VariableDeclarationStatement(name=aux_var, quantum_type=QuantumNumeric())
|
@@ -156,10 +201,6 @@ class QuantumAssignmentOperationEmitter(
|
|
156
201
|
expression=new_expression,
|
157
202
|
operation_kind=ArithmeticOperationKind.Assignment,
|
158
203
|
)
|
159
|
-
if qe.operation_kind == ArithmeticOperationKind.InplaceXor:
|
160
|
-
op = BinaryOperation.Xor
|
161
|
-
else:
|
162
|
-
op = BinaryOperation.Addition
|
163
204
|
inplace_store = InplaceBinaryOperation(
|
164
205
|
operation=op,
|
165
206
|
target=qe.result_var,
|
@@ -12,8 +12,8 @@ from classiq.model_expansions.scope import Evaluated, QuantumSymbol
|
|
12
12
|
|
13
13
|
class VariableDeclarationStatementEmitter(Emitter[VariableDeclarationStatement]):
|
14
14
|
def emit(self, variable_declaration: VariableDeclarationStatement, /) -> None:
|
15
|
-
var_decl = variable_declaration.
|
16
|
-
var_decl.quantum_type = variable_declaration.quantum_type.
|
15
|
+
var_decl = variable_declaration.model_copy()
|
16
|
+
var_decl.quantum_type = variable_declaration.quantum_type.model_copy()
|
17
17
|
self._current_scope[variable_declaration.name] = Evaluated(
|
18
18
|
value=QuantumSymbol(
|
19
19
|
handle=HandleBinding(name=var_decl.name),
|
@@ -19,7 +19,7 @@ class WithinApplyEmitter(Emitter[WithinApply]):
|
|
19
19
|
within_apply_context = self._register_generative_context(
|
20
20
|
within_apply, WITHIN_APPLY_NAME, ["within", "apply"]
|
21
21
|
)
|
22
|
-
within_apply = within_apply.
|
22
|
+
within_apply = within_apply.model_copy(
|
23
23
|
update={
|
24
24
|
"compute": within_apply_context.statements("within"),
|
25
25
|
"action": within_apply_context.statements("apply"),
|
classiq/qmod/__init__.py
CHANGED
@@ -8,6 +8,7 @@ from .qmod_constant import QConstant
|
|
8
8
|
from .qmod_parameter import Array, CArray, CBool, CInt, CReal
|
9
9
|
from .qmod_variable import Input, Output, QArray, QBit, QNum, QStruct
|
10
10
|
from .quantum_callable import QCallable, QCallableList
|
11
|
+
from .synthesize_separately import synthesize_separately
|
11
12
|
from .write_qmod import write_qmod
|
12
13
|
|
13
14
|
__all__ = [
|
@@ -30,4 +31,5 @@ __all__ = [
|
|
30
31
|
"get_expression_numeric_attributes",
|
31
32
|
"qfunc",
|
32
33
|
"write_qmod",
|
34
|
+
"synthesize_separately",
|
33
35
|
] + _builtins_all
|
@@ -17,9 +17,7 @@ from .operations import __all__ as _builtin_operations
|
|
17
17
|
from .structs import * # noqa: F403
|
18
18
|
from .structs import __all__ as _builtin_structs
|
19
19
|
|
20
|
-
FinanceFunctionInput.
|
21
|
-
FinanceFunctionType=FinanceFunctionType # noqa: F405
|
22
|
-
)
|
20
|
+
FinanceFunctionInput.model_rebuild()
|
23
21
|
BUILTIN_CONSTANTS = [
|
24
22
|
constant._get_constant_node()
|
25
23
|
for constant in [
|
@@ -22,6 +22,7 @@ from .standard_gates import *
|
|
22
22
|
from .state_preparation import *
|
23
23
|
from .state_preparation import _prepare_uniform_trimmed_state_step
|
24
24
|
from .swap_test import *
|
25
|
+
from .variational import *
|
25
26
|
|
26
27
|
CORE_LIB_DECLS = [
|
27
28
|
func.func_decl
|
@@ -69,6 +70,8 @@ CORE_LIB_DECLS = [
|
|
69
70
|
add,
|
70
71
|
modular_add,
|
71
72
|
integer_xor,
|
73
|
+
modular_add_constant,
|
74
|
+
real_xor_constant,
|
72
75
|
U,
|
73
76
|
CCX,
|
74
77
|
allocate,
|
@@ -136,6 +139,8 @@ OPEN_LIB_DECLS = [
|
|
136
139
|
_qct_d_operator,
|
137
140
|
_qct_pi_operator,
|
138
141
|
_check_msb,
|
142
|
+
encode_in_angle,
|
143
|
+
encode_on_bloch,
|
139
144
|
)
|
140
145
|
]
|
141
146
|
|
@@ -192,6 +197,8 @@ __all__ = [
|
|
192
197
|
"add",
|
193
198
|
"modular_add",
|
194
199
|
"integer_xor",
|
200
|
+
"modular_add_constant",
|
201
|
+
"real_xor_constant",
|
195
202
|
"U",
|
196
203
|
"CCX",
|
197
204
|
"allocate",
|
@@ -248,4 +255,6 @@ __all__ = [
|
|
248
255
|
"qst_type2",
|
249
256
|
"modular_increment",
|
250
257
|
"qft",
|
258
|
+
"encode_in_angle",
|
259
|
+
"encode_on_bloch",
|
251
260
|
]
|
@@ -43,11 +43,21 @@ def modular_add(left: QArray[QBit], right: QArray[QBit]) -> None:
|
|
43
43
|
pass
|
44
44
|
|
45
45
|
|
46
|
+
@qfunc(external=True)
|
47
|
+
def modular_add_constant(left: CReal, right: QNum) -> None:
|
48
|
+
pass
|
49
|
+
|
50
|
+
|
46
51
|
@qfunc(external=True)
|
47
52
|
def integer_xor(left: QArray[QBit], right: QArray[QBit]) -> None:
|
48
53
|
pass
|
49
54
|
|
50
55
|
|
56
|
+
@qfunc(external=True)
|
57
|
+
def real_xor_constant(left: CReal, right: QNum) -> None:
|
58
|
+
pass
|
59
|
+
|
60
|
+
|
51
61
|
@qfunc(external=True)
|
52
62
|
def modular_increment(a: CInt, x: QNum) -> None:
|
53
63
|
"""
|