classiq 0.88.0__py3-none-any.whl → 0.90.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of classiq might be problematic. Click here for more details.
- classiq/__init__.py +1 -0
- classiq/_internals/api_wrapper.py +16 -32
- classiq/_internals/config.py +1 -1
- classiq/analyzer/show_interactive_hack.py +26 -1
- classiq/applications/chemistry/chemistry_model_constructor.py +14 -2
- classiq/applications/combinatorial_helpers/pyomo_utils.py +9 -6
- classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +2 -2
- classiq/applications/combinatorial_optimization/combinatorial_problem.py +16 -8
- classiq/evaluators/classical_expression.py +63 -41
- classiq/evaluators/control.py +31 -52
- classiq/evaluators/expression_evaluator.py +8 -4
- classiq/evaluators/parameter_types.py +200 -104
- classiq/evaluators/qmod_annotated_expression.py +10 -9
- classiq/evaluators/qmod_expression_visitors/qmod_expression_evaluator.py +2 -2
- classiq/evaluators/qmod_expression_visitors/qmod_expression_renamer.py +1 -1
- classiq/evaluators/qmod_node_evaluators/attribute_evaluation.py +66 -5
- classiq/evaluators/qmod_node_evaluators/classical_function_evaluation.py +12 -37
- classiq/evaluators/qmod_node_evaluators/constant_evaluation.py +8 -17
- classiq/evaluators/qmod_node_evaluators/measurement_evaluation.py +1 -1
- classiq/evaluators/qmod_node_evaluators/min_max_evaluation.py +7 -1
- classiq/evaluators/qmod_node_evaluators/name_evaluation.py +0 -1
- classiq/evaluators/qmod_node_evaluators/numeric_attrs_utils.py +9 -1
- classiq/evaluators/qmod_node_evaluators/utils.py +33 -0
- classiq/evaluators/qmod_type_inference/classical_type_inference.py +4 -7
- classiq/interface/_version.py +1 -1
- classiq/interface/analyzer/analysis_params.py +2 -26
- classiq/interface/analyzer/result.py +4 -0
- classiq/interface/backend/backend_preferences.py +1 -1
- classiq/interface/chemistry/ground_state_problem.py +16 -2
- classiq/interface/executor/optimizer_preferences.py +0 -112
- classiq/interface/generator/application_apis/chemistry_declarations.py +3 -1
- classiq/interface/generator/arith/arithmetic_expression_validator.py +2 -7
- classiq/interface/generator/arith/register_user_input.py +1 -1
- classiq/interface/generator/expressions/evaluated_expression.py +3 -13
- classiq/interface/generator/expressions/expression_types.py +8 -22
- classiq/interface/generator/expressions/proxies/classical/classical_proxy.py +2 -2
- classiq/interface/generator/expressions/proxies/classical/classical_struct_proxy.py +1 -2
- classiq/interface/generator/functions/classical_type.py +24 -3
- classiq/interface/generator/functions/concrete_types.py +1 -1
- classiq/interface/generator/functions/function_declaration.py +0 -4
- classiq/interface/generator/functions/type_name.py +25 -0
- classiq/interface/generator/generated_circuit_data.py +4 -0
- classiq/interface/generator/hardware_efficient_ansatz.py +1 -1
- classiq/interface/generator/preferences/qasm_to_qmod_params.py +14 -0
- classiq/interface/generator/quantum_function_call.py +3 -3
- classiq/interface/generator/user_defined_function_params.py +0 -3
- classiq/interface/helpers/model_normalizer.py +0 -6
- classiq/interface/ide/ide_data.py +1 -1
- classiq/interface/ide/visual_model.py +3 -2
- classiq/interface/model/block.py +5 -1
- classiq/interface/model/handle_binding.py +2 -2
- classiq/interface/model/port_declaration.py +2 -1
- classiq/interface/model/quantum_expressions/arithmetic_operation.py +16 -12
- classiq/interface/model/quantum_lambda_function.py +1 -1
- classiq/interface/model/quantum_statement.py +2 -4
- classiq/interface/model/quantum_type.py +47 -4
- classiq/interface/server/routes.py +2 -3
- classiq/model_expansions/atomic_expression_functions_defs.py +4 -22
- classiq/model_expansions/capturing/captured_vars.py +7 -3
- classiq/model_expansions/closure.py +8 -0
- classiq/model_expansions/interpreters/base_interpreter.py +84 -22
- classiq/model_expansions/interpreters/frontend_generative_interpreter.py +1 -1
- classiq/model_expansions/interpreters/generative_interpreter.py +7 -5
- classiq/model_expansions/quantum_operations/allocate.py +92 -21
- classiq/model_expansions/quantum_operations/assignment_result_processor.py +28 -27
- classiq/model_expansions/quantum_operations/call_emitter.py +32 -26
- classiq/model_expansions/quantum_operations/classical_var_emitter.py +6 -2
- classiq/model_expansions/quantum_operations/emitter.py +39 -69
- classiq/model_expansions/quantum_operations/expression_evaluator.py +13 -2
- classiq/model_expansions/quantum_operations/quantum_function_call.py +4 -5
- classiq/model_expansions/quantum_operations/variable_decleration.py +16 -11
- classiq/model_expansions/scope.py +36 -29
- classiq/model_expansions/scope_initialization.py +3 -6
- classiq/model_expansions/sympy_conversion/sympy_to_python.py +6 -2
- classiq/model_expansions/transformers/model_renamer.py +35 -64
- classiq/model_expansions/transformers/type_modifier_inference.py +6 -6
- classiq/model_expansions/visitors/boolean_expression_transformers.py +7 -31
- classiq/model_expansions/visitors/symbolic_param_inference.py +9 -3
- classiq/open_library/functions/__init__.py +2 -0
- classiq/open_library/functions/state_preparation.py +140 -5
- classiq/qmod/builtins/functions/allocation.py +8 -8
- classiq/qmod/builtins/functions/arithmetic.py +1 -1
- classiq/qmod/builtins/functions/chemistry.py +64 -0
- classiq/qmod/builtins/functions/exponentiation.py +7 -13
- classiq/qmod/builtins/functions/qsvm.py +1 -1
- classiq/qmod/builtins/operations.py +38 -10
- classiq/qmod/generative.py +2 -4
- classiq/qmod/native/pretty_printer.py +1 -1
- classiq/qmod/pretty_print/pretty_printer.py +1 -1
- classiq/qmod/qmod_constant.py +1 -1
- classiq/qmod/qmod_parameter.py +2 -2
- classiq/qmod/qmod_variable.py +62 -16
- classiq/qmod/quantum_expandable.py +1 -1
- classiq/synthesis.py +37 -1
- classiq/visualization.py +1 -1
- {classiq-0.88.0.dist-info → classiq-0.90.0.dist-info}/METADATA +2 -2
- {classiq-0.88.0.dist-info → classiq-0.90.0.dist-info}/RECORD +98 -102
- classiq/evaluators/arg_type_match.py +0 -168
- classiq/evaluators/classical_type_inference.py +0 -121
- classiq/interface/combinatorial_optimization/optimization_problem.py +0 -17
- classiq/interface/combinatorial_optimization/result.py +0 -9
- classiq/model_expansions/transformers/ast_renamer.py +0 -26
- {classiq-0.88.0.dist-info → classiq-0.90.0.dist-info}/WHEEL +0 -0
|
@@ -2,7 +2,7 @@ from itertools import chain
|
|
|
2
2
|
from typing import TYPE_CHECKING, Any, Literal, Optional
|
|
3
3
|
|
|
4
4
|
import pydantic
|
|
5
|
-
from pydantic import
|
|
5
|
+
from pydantic import PrivateAttr
|
|
6
6
|
from typing_extensions import Self
|
|
7
7
|
|
|
8
8
|
from classiq.interface.ast_node import HashableASTNode
|
|
@@ -34,8 +34,6 @@ if TYPE_CHECKING:
|
|
|
34
34
|
class ClassicalType(HashableASTNode):
|
|
35
35
|
_is_generative: bool = PrivateAttr(default=False)
|
|
36
36
|
|
|
37
|
-
model_config = ConfigDict(extra="forbid")
|
|
38
|
-
|
|
39
37
|
def __str__(self) -> str:
|
|
40
38
|
return str(type(self).__name__)
|
|
41
39
|
|
|
@@ -78,6 +76,9 @@ class ClassicalType(HashableASTNode):
|
|
|
78
76
|
def get_raw_type(self) -> "ConcreteClassicalType":
|
|
79
77
|
return self # type:ignore[return-value]
|
|
80
78
|
|
|
79
|
+
def without_symbolic_attributes(self) -> Self:
|
|
80
|
+
return self
|
|
81
|
+
|
|
81
82
|
|
|
82
83
|
class Integer(ClassicalType):
|
|
83
84
|
kind: Literal["int"]
|
|
@@ -203,6 +204,18 @@ class ClassicalArray(ClassicalType):
|
|
|
203
204
|
def raw_qmod_type_name(self) -> str:
|
|
204
205
|
return "CArray"
|
|
205
206
|
|
|
207
|
+
def without_symbolic_attributes(self) -> "ClassicalArray":
|
|
208
|
+
length = (
|
|
209
|
+
None
|
|
210
|
+
if self.length is None
|
|
211
|
+
or not self.length.is_evaluated()
|
|
212
|
+
or not self.length.is_constant()
|
|
213
|
+
else self.length
|
|
214
|
+
)
|
|
215
|
+
return ClassicalArray(
|
|
216
|
+
element_type=self.element_type.without_symbolic_attributes(), length=length
|
|
217
|
+
)
|
|
218
|
+
|
|
206
219
|
|
|
207
220
|
class ClassicalTuple(ClassicalType):
|
|
208
221
|
kind: Literal["tuple"]
|
|
@@ -273,6 +286,14 @@ class ClassicalTuple(ClassicalType):
|
|
|
273
286
|
def raw_qmod_type_name(self) -> str:
|
|
274
287
|
return "CArray"
|
|
275
288
|
|
|
289
|
+
def without_symbolic_attributes(self) -> "ClassicalTuple":
|
|
290
|
+
return ClassicalTuple(
|
|
291
|
+
element_types=[
|
|
292
|
+
element_type.without_symbolic_attributes()
|
|
293
|
+
for element_type in self.element_types
|
|
294
|
+
]
|
|
295
|
+
)
|
|
296
|
+
|
|
276
297
|
|
|
277
298
|
class OpaqueHandle(ClassicalType):
|
|
278
299
|
pass
|
|
@@ -47,7 +47,7 @@ PythonClassicalPydanticTypes = (Enum,)
|
|
|
47
47
|
|
|
48
48
|
ConcreteQuantumType = Annotated[
|
|
49
49
|
Union[QuantumBit, QuantumBitvector, QuantumNumeric, TypeName],
|
|
50
|
-
Field(discriminator="kind"
|
|
50
|
+
Field(discriminator="kind"),
|
|
51
51
|
]
|
|
52
52
|
QuantumBitvector.model_rebuild()
|
|
53
53
|
TypeName.model_rebuild()
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import abc
|
|
2
2
|
from collections.abc import Sequence
|
|
3
3
|
|
|
4
|
-
from pydantic import ConfigDict
|
|
5
|
-
|
|
6
4
|
from classiq.interface.model.classical_parameter_declaration import (
|
|
7
5
|
AnonClassicalParameterDeclaration,
|
|
8
6
|
)
|
|
@@ -19,7 +17,5 @@ class FunctionDeclaration(Parameter, abc.ABC):
|
|
|
19
17
|
def param_decls(self) -> Sequence["AnonClassicalParameterDeclaration"]:
|
|
20
18
|
pass
|
|
21
19
|
|
|
22
|
-
model_config = ConfigDict(extra="forbid")
|
|
23
|
-
|
|
24
20
|
|
|
25
21
|
FunctionDeclaration.model_rebuild()
|
|
@@ -189,6 +189,31 @@ class TypeName(ClassicalType, QuantumType):
|
|
|
189
189
|
field_type.minimal_size_in_bits for field_type in self.fields.values()
|
|
190
190
|
)
|
|
191
191
|
|
|
192
|
+
def without_symbolic_attributes(self) -> "TypeName":
|
|
193
|
+
if self.has_fields:
|
|
194
|
+
type_name = TypeName(name=self.name)
|
|
195
|
+
type_name.set_fields(
|
|
196
|
+
{
|
|
197
|
+
field_name: field_type.without_symbolic_attributes()
|
|
198
|
+
for field_name, field_type in self.fields.items()
|
|
199
|
+
}
|
|
200
|
+
)
|
|
201
|
+
return type_name
|
|
202
|
+
if self.has_classical_struct_decl:
|
|
203
|
+
type_name = TypeName(name=self.name)
|
|
204
|
+
type_name.set_classical_struct_decl(
|
|
205
|
+
self.classical_struct_decl.model_copy(
|
|
206
|
+
update=dict(
|
|
207
|
+
variables={
|
|
208
|
+
field_name: field_type.without_symbolic_attributes()
|
|
209
|
+
for field_name, field_type in self.classical_struct_decl.variables.items()
|
|
210
|
+
}
|
|
211
|
+
)
|
|
212
|
+
)
|
|
213
|
+
)
|
|
214
|
+
return type_name
|
|
215
|
+
return self
|
|
216
|
+
|
|
192
217
|
|
|
193
218
|
class Enum(TypeName):
|
|
194
219
|
pass
|
|
@@ -17,6 +17,7 @@ from classiq.interface.generator.register_role import RegisterRole
|
|
|
17
17
|
from classiq.interface.generator.synthesis_metadata.synthesis_execution_data import (
|
|
18
18
|
ExecutionData,
|
|
19
19
|
)
|
|
20
|
+
from classiq.interface.model.block import Block
|
|
20
21
|
from classiq.interface.model.quantum_expressions.arithmetic_operation import (
|
|
21
22
|
ArithmeticOperationKind,
|
|
22
23
|
)
|
|
@@ -210,10 +211,13 @@ class FunctionDebugInfoInterface(pydantic.BaseModel):
|
|
|
210
211
|
)
|
|
211
212
|
name_with_suffix = self.add_suffix_from_generated_name(generated_name, name)
|
|
212
213
|
return name_with_suffix
|
|
214
|
+
if isinstance(back_ref, Block) and back_ref.label is not None:
|
|
215
|
+
return back_ref.label
|
|
213
216
|
|
|
214
217
|
statement_kind: str = back_ref.kind
|
|
215
218
|
if isinstance(back_ref, ArithmeticOperation):
|
|
216
219
|
statement_kind = back_ref.operation_kind.value
|
|
220
|
+
|
|
217
221
|
return self.add_suffix_from_generated_name(
|
|
218
222
|
generated_name, STATEMENTS_NAME[statement_kind]
|
|
219
223
|
)
|
|
@@ -42,7 +42,7 @@ class HardwareEfficientAnsatz(function_params.FunctionParams):
|
|
|
42
42
|
"If none specified - use connectivity map from the model hardware settings. "
|
|
43
43
|
"If none specified as well, all qubit pairs will be connected.",
|
|
44
44
|
)
|
|
45
|
-
num_qubits: pydantic.PositiveInt = pydantic.Field(
|
|
45
|
+
num_qubits: pydantic.PositiveInt = pydantic.Field( # type: ignore[assignment]
|
|
46
46
|
default=None,
|
|
47
47
|
description="Number of qubits in the ansatz.",
|
|
48
48
|
validate_default=True,
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from pydantic import BaseModel
|
|
2
|
+
|
|
3
|
+
from classiq.interface.analyzer.result import QasmCode
|
|
4
|
+
from classiq.interface.enum_utils import StrEnum
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class QmodFormat(StrEnum):
|
|
8
|
+
NATIVE = "native"
|
|
9
|
+
PYTHON = "python"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class QasmToQmodParams(BaseModel):
|
|
13
|
+
qasm: QasmCode
|
|
14
|
+
qmod_format: QmodFormat
|
|
@@ -130,7 +130,7 @@ class SynthesisQuantumFunctionCall(BaseModel):
|
|
|
130
130
|
default=True,
|
|
131
131
|
description="False value indicates this call shouldn't be controlled even if the flow is controlled.",
|
|
132
132
|
)
|
|
133
|
-
inputs: IOType = pydantic.Field(
|
|
133
|
+
inputs: IOType = pydantic.Field( # type: ignore[assignment]
|
|
134
134
|
default_factory=dict,
|
|
135
135
|
description="A mapping from the input name to the wire it connects to",
|
|
136
136
|
)
|
|
@@ -138,14 +138,14 @@ class SynthesisQuantumFunctionCall(BaseModel):
|
|
|
138
138
|
default_factory=dict,
|
|
139
139
|
description="A mapping from in/out name to the wires that connect to it",
|
|
140
140
|
)
|
|
141
|
-
outputs: IOType = pydantic.Field(
|
|
141
|
+
outputs: IOType = pydantic.Field( # type: ignore[assignment]
|
|
142
142
|
default_factory=dict,
|
|
143
143
|
description="A mapping from the output name to the wire it connects to",
|
|
144
144
|
)
|
|
145
145
|
power: PydanticPowerType = pydantic.Field(
|
|
146
146
|
default=1, description="Number of successive calls to the operation"
|
|
147
147
|
)
|
|
148
|
-
name: PydanticNonEmptyString = pydantic.Field(
|
|
148
|
+
name: PydanticNonEmptyString = pydantic.Field( # type: ignore[assignment]
|
|
149
149
|
default=None,
|
|
150
150
|
validate_default=True,
|
|
151
151
|
description="The name of the function instance. "
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
from collections.abc import Mapping
|
|
2
2
|
|
|
3
3
|
import pydantic
|
|
4
|
-
from pydantic import ConfigDict
|
|
5
4
|
|
|
6
5
|
from classiq.interface.generator.arith.register_user_input import RegisterArithmeticInfo
|
|
7
6
|
from classiq.interface.generator.function_params import ArithmeticIODict, FunctionParams
|
|
@@ -12,8 +11,6 @@ class CustomFunction(FunctionParams):
|
|
|
12
11
|
A user-defined custom function parameters object.
|
|
13
12
|
"""
|
|
14
13
|
|
|
15
|
-
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
16
|
-
|
|
17
14
|
_name: str = pydantic.PrivateAttr(default="")
|
|
18
15
|
|
|
19
16
|
input_decls: ArithmeticIODict = pydantic.Field(
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import ast
|
|
2
1
|
from typing import Any
|
|
3
2
|
|
|
4
3
|
from classiq.interface.ast_node import ASTNode
|
|
@@ -10,8 +9,6 @@ from classiq.interface.generator.visitor import Transformer, Visitor
|
|
|
10
9
|
from classiq.interface.model.model import Model
|
|
11
10
|
from classiq.interface.model.port_declaration import AnonPortDeclaration
|
|
12
11
|
|
|
13
|
-
from classiq.model_expansions.transformers.model_renamer import ExprNormalizer
|
|
14
|
-
|
|
15
12
|
|
|
16
13
|
class ModelNormalizer(Visitor):
|
|
17
14
|
def visit(self, node: Any) -> None:
|
|
@@ -28,9 +25,6 @@ class ModelNormalizer(Visitor):
|
|
|
28
25
|
model.functions.sort(key=lambda x: x.name)
|
|
29
26
|
self.generic_visit(model)
|
|
30
27
|
|
|
31
|
-
def visit_Expression(self, expr: Expression) -> None:
|
|
32
|
-
expr.expr = ast.unparse(ExprNormalizer().visit(ast.parse(expr.expr)))
|
|
33
|
-
|
|
34
28
|
def visit_AnonPortDeclaration(self, decl: AnonPortDeclaration) -> None:
|
|
35
29
|
decl.type_modifier = TypeModifier.Mutable
|
|
36
30
|
|
|
@@ -59,7 +59,7 @@ class IDEDataOperation(pydantic.BaseModel):
|
|
|
59
59
|
_qubits: list = pydantic.PrivateAttr() # list[Qubit]
|
|
60
60
|
|
|
61
61
|
displayArgs: str = ""
|
|
62
|
-
targets: Union[list[IDEQubitDef], list[IDEClassicalBitDef]] = pydantic.Field(
|
|
62
|
+
targets: Union[list[IDEQubitDef], list[IDEClassicalBitDef]] = pydantic.Field( # type: ignore[assignment]
|
|
63
63
|
default_factory=list
|
|
64
64
|
)
|
|
65
65
|
controls: list[IDEQubitDef] = list()
|
|
@@ -171,6 +171,7 @@ class Operation(pydantic.BaseModel):
|
|
|
171
171
|
expanded: bool = pydantic.Field(default=False)
|
|
172
172
|
show_expanded_label: bool = pydantic.Field(default=False)
|
|
173
173
|
is_low_level_fallback: bool = pydantic.Field(default=False)
|
|
174
|
+
is_measurement: bool = pydantic.Field(default=False)
|
|
174
175
|
|
|
175
176
|
model_config = ConfigDict(frozen=True)
|
|
176
177
|
|
|
@@ -207,9 +208,9 @@ class Operation(pydantic.BaseModel):
|
|
|
207
208
|
|
|
208
209
|
|
|
209
210
|
class ProgramVisualModel(VersionedModel):
|
|
210
|
-
main_operation: Operation = pydantic.Field(default=None)
|
|
211
|
+
main_operation: Operation = pydantic.Field(default=None) # type: ignore[assignment]
|
|
211
212
|
id_to_operations: dict[int, Operation] = pydantic.Field(default_factory=dict)
|
|
212
|
-
main_operation_id: int = pydantic.Field(default=None)
|
|
213
|
+
main_operation_id: int = pydantic.Field(default=None) # type: ignore[assignment]
|
|
213
214
|
program_data: ProgramData
|
|
214
215
|
|
|
215
216
|
@property
|
classiq/interface/model/block.py
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
from typing import TYPE_CHECKING, Literal
|
|
1
|
+
from typing import TYPE_CHECKING, Literal, Optional
|
|
2
|
+
|
|
3
|
+
import pydantic
|
|
2
4
|
|
|
3
5
|
from classiq.interface.model.quantum_statement import QuantumOperation
|
|
4
6
|
|
|
@@ -10,3 +12,5 @@ class Block(QuantumOperation):
|
|
|
10
12
|
kind: Literal["Block"]
|
|
11
13
|
|
|
12
14
|
statements: "StatementBlock"
|
|
15
|
+
|
|
16
|
+
label: Optional[str] = pydantic.Field(default=None)
|
|
@@ -19,7 +19,7 @@ def _get_expr_id(expr: Expression) -> str:
|
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
class HandleBinding(ASTNode):
|
|
22
|
-
name: str = Field(default=None)
|
|
22
|
+
name: str = Field(default=None) # type: ignore[assignment]
|
|
23
23
|
model_config = ConfigDict(frozen=True, extra="forbid")
|
|
24
24
|
|
|
25
25
|
def __str__(self) -> str:
|
|
@@ -349,7 +349,7 @@ class FieldHandleBinding(NestedHandleBinding):
|
|
|
349
349
|
|
|
350
350
|
@property
|
|
351
351
|
def qmod_expr(self) -> str:
|
|
352
|
-
return f"
|
|
352
|
+
return f"{self.base_handle.qmod_expr}.{self.field}"
|
|
353
353
|
|
|
354
354
|
@property
|
|
355
355
|
def identifier(self) -> str:
|
|
@@ -13,10 +13,11 @@ from classiq.interface.generator.functions.type_modifier import (
|
|
|
13
13
|
)
|
|
14
14
|
from classiq.interface.helpers.pydantic_model_helpers import values_with_discriminator
|
|
15
15
|
from classiq.interface.model.parameter import Parameter
|
|
16
|
+
from classiq.interface.model.quantum_type import QuantumBitvector
|
|
16
17
|
|
|
17
18
|
|
|
18
19
|
class AnonPortDeclaration(Parameter):
|
|
19
|
-
quantum_type: ConcreteQuantumType
|
|
20
|
+
quantum_type: ConcreteQuantumType = pydantic.Field(default_factory=QuantumBitvector)
|
|
20
21
|
direction: PortDeclarationDirection
|
|
21
22
|
kind: Literal["PortDeclaration"]
|
|
22
23
|
type_modifier: TypeModifier
|
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
from collections.abc import Mapping, Sequence
|
|
2
|
-
from typing import Literal
|
|
3
|
-
|
|
4
|
-
from pydantic import PrivateAttr
|
|
2
|
+
from typing import Literal, cast
|
|
5
3
|
|
|
6
4
|
from classiq.interface.enum_utils import StrEnum
|
|
7
5
|
from classiq.interface.generator.arith.arithmetic import (
|
|
8
6
|
ARITHMETIC_EXPRESSION_RESULT_NAME,
|
|
9
|
-
compute_arithmetic_result_type,
|
|
10
7
|
)
|
|
11
8
|
from classiq.interface.model.handle_binding import (
|
|
12
9
|
ConcreteHandleBinding,
|
|
@@ -18,6 +15,9 @@ from classiq.interface.model.quantum_expressions.quantum_expression import (
|
|
|
18
15
|
from classiq.interface.model.quantum_statement import HandleMetadata
|
|
19
16
|
from classiq.interface.model.quantum_type import QuantumType
|
|
20
17
|
|
|
18
|
+
from classiq.evaluators.qmod_annotated_expression import QmodAnnotatedExpression
|
|
19
|
+
from classiq.model_expansions.arithmetic import NumericAttributes
|
|
20
|
+
|
|
21
21
|
|
|
22
22
|
class ArithmeticOperationKind(StrEnum):
|
|
23
23
|
InplaceAdd = "inplace_add"
|
|
@@ -29,7 +29,7 @@ class ArithmeticOperation(QuantumAssignmentOperation):
|
|
|
29
29
|
kind: Literal["ArithmeticOperation"]
|
|
30
30
|
|
|
31
31
|
operation_kind: ArithmeticOperationKind
|
|
32
|
-
|
|
32
|
+
classical_assignment: bool = False
|
|
33
33
|
|
|
34
34
|
@property
|
|
35
35
|
def is_inplace(self) -> bool:
|
|
@@ -44,16 +44,20 @@ class ArithmeticOperation(QuantumAssignmentOperation):
|
|
|
44
44
|
machine_precision: int,
|
|
45
45
|
) -> None:
|
|
46
46
|
super().initialize_var_types(var_types, machine_precision)
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
expr_val = self.expression.value.value
|
|
48
|
+
if isinstance(expr_val, QmodAnnotatedExpression):
|
|
49
|
+
self._result_type = expr_val.get_quantum_type(expr_val.root)
|
|
50
|
+
else:
|
|
51
|
+
self._result_type = NumericAttributes.from_constant(
|
|
52
|
+
cast(float, expr_val), machine_precision
|
|
53
|
+
).to_quantum_numeric()
|
|
50
54
|
|
|
51
55
|
@property
|
|
52
56
|
def wiring_inouts(
|
|
53
57
|
self,
|
|
54
58
|
) -> Mapping[str, ConcreteHandleBinding]:
|
|
55
59
|
inouts = dict(super().wiring_inouts)
|
|
56
|
-
if self.is_inplace and not self.
|
|
60
|
+
if self.is_inplace and not self.classical_assignment:
|
|
57
61
|
inouts[self.result_name()] = self.result_var
|
|
58
62
|
return inouts
|
|
59
63
|
|
|
@@ -63,7 +67,7 @@ class ArithmeticOperation(QuantumAssignmentOperation):
|
|
|
63
67
|
HandleMetadata(handle=handle, readable_location="in an expression")
|
|
64
68
|
for handle in self.var_handles
|
|
65
69
|
]
|
|
66
|
-
if self.is_inplace and not self.
|
|
70
|
+
if self.is_inplace and not self.classical_assignment:
|
|
67
71
|
inouts.append(
|
|
68
72
|
HandleMetadata(
|
|
69
73
|
handle=self.result_var,
|
|
@@ -74,13 +78,13 @@ class ArithmeticOperation(QuantumAssignmentOperation):
|
|
|
74
78
|
|
|
75
79
|
@property
|
|
76
80
|
def wiring_outputs(self) -> Mapping[str, HandleBinding]:
|
|
77
|
-
if self.is_inplace or self.
|
|
81
|
+
if self.is_inplace or self.classical_assignment:
|
|
78
82
|
return {}
|
|
79
83
|
return super().wiring_outputs
|
|
80
84
|
|
|
81
85
|
@property
|
|
82
86
|
def readable_outputs(self) -> Sequence[HandleMetadata]:
|
|
83
|
-
if self.is_inplace or self.
|
|
87
|
+
if self.is_inplace or self.classical_assignment:
|
|
84
88
|
return []
|
|
85
89
|
return [
|
|
86
90
|
HandleMetadata(
|
|
@@ -32,7 +32,7 @@ class QuantumLambdaFunction(ASTNode):
|
|
|
32
32
|
default=None
|
|
33
33
|
)
|
|
34
34
|
|
|
35
|
-
_py_callable: Callable = pydantic.PrivateAttr(default=None)
|
|
35
|
+
_py_callable: Callable = pydantic.PrivateAttr(default=None) # type: ignore[assignment]
|
|
36
36
|
|
|
37
37
|
@property
|
|
38
38
|
def py_callable(self) -> Callable:
|
|
@@ -4,7 +4,6 @@ from typing import Any, Callable, Optional
|
|
|
4
4
|
from uuid import UUID, uuid4
|
|
5
5
|
|
|
6
6
|
import pydantic
|
|
7
|
-
from pydantic import ConfigDict
|
|
8
7
|
from typing_extensions import Self
|
|
9
8
|
|
|
10
9
|
from classiq.interface.ast_node import ASTNode
|
|
@@ -21,7 +20,6 @@ from classiq.interface.model.handle_binding import (
|
|
|
21
20
|
|
|
22
21
|
class QuantumStatement(ASTNode):
|
|
23
22
|
kind: str
|
|
24
|
-
model_config = ConfigDict(extra="forbid")
|
|
25
23
|
uuid: UUID = pydantic.Field(
|
|
26
24
|
description="A unique identifier for this operation", default_factory=uuid4
|
|
27
25
|
)
|
|
@@ -29,12 +27,12 @@ class QuantumStatement(ASTNode):
|
|
|
29
27
|
def model_copy(
|
|
30
28
|
self,
|
|
31
29
|
*,
|
|
32
|
-
update: Optional[
|
|
30
|
+
update: Optional[Mapping[str, Any]] = None,
|
|
33
31
|
deep: bool = False,
|
|
34
32
|
keep_uuid: bool = False,
|
|
35
33
|
) -> Self:
|
|
36
34
|
if not keep_uuid:
|
|
37
|
-
update = update
|
|
35
|
+
update = dict(update) if update is not None else dict()
|
|
38
36
|
update.setdefault("uuid", uuid4())
|
|
39
37
|
return super().model_copy(update=update, deep=deep)
|
|
40
38
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from typing import TYPE_CHECKING, Any, Literal, Optional
|
|
2
2
|
|
|
3
3
|
import pydantic
|
|
4
|
-
from pydantic import BaseModel,
|
|
4
|
+
from pydantic import BaseModel, Field
|
|
5
5
|
from typing_extensions import Self
|
|
6
6
|
|
|
7
7
|
from classiq.interface.ast_node import HashableASTNode
|
|
@@ -35,8 +35,6 @@ if TYPE_CHECKING:
|
|
|
35
35
|
|
|
36
36
|
|
|
37
37
|
class QuantumType(HashableASTNode):
|
|
38
|
-
model_config = ConfigDict(extra="forbid")
|
|
39
|
-
|
|
40
38
|
_size_in_bits: Optional[int] = pydantic.PrivateAttr(default=None)
|
|
41
39
|
|
|
42
40
|
def _update_size_in_bits_from_declaration(self) -> None:
|
|
@@ -92,6 +90,9 @@ class QuantumType(HashableASTNode):
|
|
|
92
90
|
def expressions(self) -> list[Expression]:
|
|
93
91
|
return []
|
|
94
92
|
|
|
93
|
+
def without_symbolic_attributes(self) -> Self:
|
|
94
|
+
return self
|
|
95
|
+
|
|
95
96
|
|
|
96
97
|
class QuantumScalar(QuantumType):
|
|
97
98
|
def get_proxy(self, handle: "HandleBinding") -> QmodQScalarProxy:
|
|
@@ -292,6 +293,18 @@ class QuantumBitvector(QuantumType):
|
|
|
292
293
|
length = 1
|
|
293
294
|
return length * self.element_type.minimal_size_in_bits
|
|
294
295
|
|
|
296
|
+
def without_symbolic_attributes(self) -> "QuantumBitvector":
|
|
297
|
+
length = (
|
|
298
|
+
None
|
|
299
|
+
if self.length is None
|
|
300
|
+
or not self.length.is_evaluated()
|
|
301
|
+
or not self.length.is_constant()
|
|
302
|
+
else self.length
|
|
303
|
+
)
|
|
304
|
+
return QuantumBitvector(
|
|
305
|
+
element_type=self.element_type.without_symbolic_attributes(), length=length
|
|
306
|
+
)
|
|
307
|
+
|
|
295
308
|
|
|
296
309
|
class QuantumNumeric(QuantumScalar):
|
|
297
310
|
kind: Literal["qnum"]
|
|
@@ -487,9 +500,39 @@ class QuantumNumeric(QuantumScalar):
|
|
|
487
500
|
def minimal_size_in_bits(self) -> int:
|
|
488
501
|
return self.size_in_bits if self.has_size_in_bits else 1
|
|
489
502
|
|
|
503
|
+
def without_symbolic_attributes(self) -> "QuantumNumeric":
|
|
504
|
+
size = (
|
|
505
|
+
None
|
|
506
|
+
if self.size is None
|
|
507
|
+
or not self.size.is_evaluated()
|
|
508
|
+
or not self.size.is_constant()
|
|
509
|
+
else self.size
|
|
510
|
+
)
|
|
511
|
+
is_signed = (
|
|
512
|
+
None
|
|
513
|
+
if self.is_signed is None
|
|
514
|
+
or not self.is_signed.is_evaluated()
|
|
515
|
+
or not self.is_signed.is_constant()
|
|
516
|
+
else self.is_signed
|
|
517
|
+
)
|
|
518
|
+
fraction_digits = (
|
|
519
|
+
None
|
|
520
|
+
if self.fraction_digits is None
|
|
521
|
+
or not self.fraction_digits.is_evaluated()
|
|
522
|
+
or not self.fraction_digits.is_constant()
|
|
523
|
+
else self.fraction_digits
|
|
524
|
+
)
|
|
525
|
+
if size is None or is_signed is None or fraction_digits is None:
|
|
526
|
+
is_signed = fraction_digits = None
|
|
527
|
+
qnum = QuantumNumeric(
|
|
528
|
+
size=size, is_signed=is_signed, fraction_digits=fraction_digits
|
|
529
|
+
)
|
|
530
|
+
qnum.set_bounds(self.get_bounds())
|
|
531
|
+
return qnum
|
|
532
|
+
|
|
490
533
|
|
|
491
534
|
class RegisterQuantumType(BaseModel):
|
|
492
|
-
quantum_types: "ConcreteQuantumType"
|
|
535
|
+
quantum_types: "ConcreteQuantumType" = Field(default_factory=QuantumBitvector)
|
|
493
536
|
size: int = Field(default=1)
|
|
494
537
|
|
|
495
538
|
@property
|
|
@@ -44,9 +44,6 @@ TASKS_VISUALIZE_SUFFIX = TASKS_SUFFIX + "/visualize"
|
|
|
44
44
|
TASKS_VISUAL_MODEL_SUFFIX = TASKS_SUFFIX + "/visual_model"
|
|
45
45
|
TASKS_SOLVE_SUFFIX = "/tasks/solve"
|
|
46
46
|
|
|
47
|
-
CHEMISTRY_QMOD_PATH = "/generate_model/chemistry/qmod"
|
|
48
|
-
|
|
49
|
-
|
|
50
47
|
TASK_TRAIN_SUFFIX = TASKS_SUFFIX + "/train"
|
|
51
48
|
TASK_TEST_SUFFIX = TASKS_SUFFIX + "/test"
|
|
52
49
|
TASK_PREDICT_SUFFIX = TASKS_SUFFIX + "/predict"
|
|
@@ -75,6 +72,8 @@ CONVERSION_GENERATED_CIRCUIT_TO_EXECUTION_INPUT_SUFFIX = "/execution_input"
|
|
|
75
72
|
CONVERSION_GENERATED_CIRCUIT_TO_EXECUTION_INPUT_FULL = (
|
|
76
73
|
CONVERSION_PREFIX + CONVERSION_GENERATED_CIRCUIT_TO_EXECUTION_INPUT_SUFFIX
|
|
77
74
|
)
|
|
75
|
+
QASM_TO_QMOD_SUFFIX = "/qasm_to_qmod"
|
|
76
|
+
QASM_TO_QMOD_FULL_PATH = CONVERSION_PREFIX + QASM_TO_QMOD_SUFFIX
|
|
78
77
|
|
|
79
78
|
STATIC_SEMANTICS_VALIDATION_PATH = "/validate_static_semantics"
|
|
80
79
|
|
|
@@ -15,6 +15,7 @@ from classiq.interface.generator.expressions.atomic_expression_functions import
|
|
|
15
15
|
from classiq.interface.generator.expressions.expression_types import (
|
|
16
16
|
ExpressionValue,
|
|
17
17
|
QmodStructInstance,
|
|
18
|
+
RuntimeConstant,
|
|
18
19
|
)
|
|
19
20
|
from classiq.interface.generator.expressions.proxies.classical.any_classical_value import (
|
|
20
21
|
AnyClassicalValue,
|
|
@@ -44,14 +45,12 @@ from classiq.interface.generator.functions.classical_type import (
|
|
|
44
45
|
ClassicalArray,
|
|
45
46
|
ClassicalTuple,
|
|
46
47
|
ClassicalType,
|
|
47
|
-
OpaqueHandle,
|
|
48
|
-
QmodPyObject,
|
|
49
48
|
Real,
|
|
50
|
-
StructMetaType,
|
|
51
49
|
)
|
|
52
50
|
from classiq.interface.generator.functions.type_name import TypeName
|
|
53
51
|
from classiq.interface.helpers.backward_compatibility import zip_strict
|
|
54
52
|
|
|
53
|
+
from classiq.evaluators.qmod_annotated_expression import QmodAnnotatedExpression
|
|
55
54
|
from classiq.evaluators.qmod_expression_visitors.sympy_wrappers import (
|
|
56
55
|
BitwiseAnd,
|
|
57
56
|
BitwiseNot,
|
|
@@ -61,10 +60,6 @@ from classiq.evaluators.qmod_expression_visitors.sympy_wrappers import (
|
|
|
61
60
|
LShift,
|
|
62
61
|
RShift,
|
|
63
62
|
)
|
|
64
|
-
from classiq.model_expansions.model_tables import (
|
|
65
|
-
HandleIdentifier,
|
|
66
|
-
HandleTable,
|
|
67
|
-
)
|
|
68
63
|
from classiq.model_expansions.sympy_conversion.expression_to_sympy import (
|
|
69
64
|
MISSING_SLICE_VALUE_PLACEHOLDER,
|
|
70
65
|
)
|
|
@@ -106,10 +101,6 @@ def qmod_val_to_python(val: ExpressionValue, qmod_type: ClassicalType) -> Any:
|
|
|
106
101
|
)
|
|
107
102
|
]
|
|
108
103
|
|
|
109
|
-
elif isinstance(qmod_type, OpaqueHandle):
|
|
110
|
-
if isinstance(val, HandleIdentifier):
|
|
111
|
-
return HandleTable.get_handle_object(val)
|
|
112
|
-
|
|
113
104
|
elif isinstance(val, Expr):
|
|
114
105
|
return sympy_to_python(val)
|
|
115
106
|
|
|
@@ -121,10 +112,6 @@ def qmod_val_to_python(val: ExpressionValue, qmod_type: ClassicalType) -> Any:
|
|
|
121
112
|
if isinstance(val, bool):
|
|
122
113
|
return val
|
|
123
114
|
|
|
124
|
-
elif isinstance(qmod_type, StructMetaType):
|
|
125
|
-
if isinstance(val, TypeProxy):
|
|
126
|
-
return val.struct_declaration
|
|
127
|
-
|
|
128
115
|
elif isinstance(val, int): # other scalars are represented as int
|
|
129
116
|
return val
|
|
130
117
|
|
|
@@ -162,11 +149,6 @@ def python_val_to_qmod(val: Any, qmod_type: ClassicalType) -> ExpressionValue:
|
|
|
162
149
|
for elem, elem_type in zip_strict(val, qmod_type.element_types, strict=True)
|
|
163
150
|
]
|
|
164
151
|
|
|
165
|
-
if isinstance(qmod_type, OpaqueHandle):
|
|
166
|
-
if not isinstance(val, QmodPyObject):
|
|
167
|
-
raise ClassiqInternalExpansionError("Bad value opaque handle")
|
|
168
|
-
return HandleTable.set_handle_object(val)
|
|
169
|
-
|
|
170
152
|
return val
|
|
171
153
|
|
|
172
154
|
|
|
@@ -194,7 +176,7 @@ def get_field(
|
|
|
194
176
|
QmodSizedProxy, QmodStructInstance, list, ClassicalProxy, AnyClassicalValue
|
|
195
177
|
],
|
|
196
178
|
field: str,
|
|
197
|
-
) ->
|
|
179
|
+
) -> Any:
|
|
198
180
|
if isinstance(proxy, AnyClassicalValue) or (
|
|
199
181
|
isinstance(proxy, Symbol)
|
|
200
182
|
and not isinstance(proxy, QmodSizedProxy)
|
|
@@ -244,7 +226,7 @@ def do_div(lhs: Any, rhs: Any) -> Any:
|
|
|
244
226
|
return res
|
|
245
227
|
|
|
246
228
|
|
|
247
|
-
_EXPRESSION_TYPES = get_args(
|
|
229
|
+
_EXPRESSION_TYPES = (*get_args(RuntimeConstant), QmodAnnotatedExpression)
|
|
248
230
|
|
|
249
231
|
|
|
250
232
|
def _is_qmod_value(val: Any) -> bool:
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import ast
|
|
1
2
|
import dataclasses
|
|
2
3
|
from collections.abc import Sequence
|
|
3
4
|
from dataclasses import dataclass, field
|
|
@@ -41,6 +42,7 @@ from classiq.interface.model.variable_declaration_statement import (
|
|
|
41
42
|
VariableDeclarationStatement,
|
|
42
43
|
)
|
|
43
44
|
|
|
45
|
+
from classiq.evaluators.qmod_annotated_expression import QmodAnnotatedExpression
|
|
44
46
|
from classiq.model_expansions.capturing.mangling_utils import (
|
|
45
47
|
demangle_handle,
|
|
46
48
|
mangle_captured_var_name,
|
|
@@ -60,9 +62,11 @@ UNINITIALIZED_VAR_MESSAGE = "Variable '{}' should be initialized here"
|
|
|
60
62
|
|
|
61
63
|
def _get_symbol_expr(symbol: str, classical_type: ClassicalType) -> Expression:
|
|
62
64
|
expr = Expression(expr=symbol)
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
)
|
|
65
|
+
expr_val = QmodAnnotatedExpression(ast.Name(id=symbol))
|
|
66
|
+
expr_val.set_type(expr_val.root, classical_type)
|
|
67
|
+
expr_val.set_var(expr_val.root, HandleBinding(name=symbol))
|
|
68
|
+
expr_val.lock()
|
|
69
|
+
expr._evaluated_expr = EvaluatedExpression(value=expr_val)
|
|
66
70
|
return expr
|
|
67
71
|
|
|
68
72
|
|