classiq 0.87.0__py3-none-any.whl → 0.89.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/_internals/config.py +1 -1
- classiq/applications/__init__.py +1 -2
- classiq/applications/combinatorial_helpers/combinatorial_problem_utils.py +1 -1
- classiq/applications/hamiltonian/pauli_decomposition.py +1 -1
- classiq/evaluators/qmod_annotated_expression.py +37 -15
- classiq/evaluators/qmod_expression_visitors/qmod_expression_bwc.py +0 -5
- classiq/evaluators/qmod_expression_visitors/qmod_expression_evaluator.py +20 -13
- classiq/evaluators/qmod_expression_visitors/qmod_expression_renamer.py +15 -8
- classiq/evaluators/qmod_expression_visitors/qmod_expression_simplifier.py +39 -16
- classiq/evaluators/qmod_node_evaluators/attribute_evaluation.py +67 -6
- classiq/evaluators/qmod_node_evaluators/classical_function_evaluation.py +18 -8
- classiq/evaluators/qmod_node_evaluators/compare_evaluation.py +8 -0
- classiq/evaluators/qmod_node_evaluators/constant_evaluation.py +4 -1
- classiq/evaluators/qmod_node_evaluators/numeric_attrs_utils.py +1 -1
- classiq/evaluators/qmod_node_evaluators/struct_instantiation_evaluation.py +1 -1
- classiq/evaluators/qmod_node_evaluators/subscript_evaluation.py +3 -3
- classiq/evaluators/qmod_node_evaluators/utils.py +1 -1
- classiq/evaluators/qmod_type_inference/classical_type_inference.py +4 -4
- classiq/evaluators/qmod_type_inference/quantum_type_inference.py +38 -0
- classiq/evaluators/type_type_match.py +1 -1
- classiq/execution/execution_session.py +17 -2
- classiq/interface/_version.py +1 -1
- classiq/interface/analyzer/analysis_params.py +1 -1
- classiq/interface/backend/backend_preferences.py +1 -1
- classiq/interface/execution/primitives.py +1 -0
- classiq/interface/generator/application_apis/__init__.py +0 -1
- classiq/interface/generator/arith/register_user_input.py +1 -1
- classiq/interface/generator/expressions/atomic_expression_functions.py +0 -2
- classiq/interface/generator/function_param_list.py +0 -4
- classiq/interface/generator/functions/classical_type.py +32 -3
- classiq/interface/generator/functions/function_declaration.py +0 -4
- classiq/interface/generator/functions/type_name.py +31 -0
- classiq/interface/generator/hardware_efficient_ansatz.py +1 -1
- classiq/interface/generator/quantum_function_call.py +3 -3
- classiq/interface/generator/transpiler_basis_gates.py +5 -1
- classiq/interface/generator/types/builtin_enum_declarations.py +0 -8
- classiq/interface/generator/user_defined_function_params.py +0 -3
- classiq/interface/ide/ide_data.py +1 -1
- classiq/interface/ide/visual_model.py +2 -2
- classiq/interface/model/block.py +5 -1
- classiq/interface/model/classical_if.py +16 -8
- classiq/interface/model/classical_parameter_declaration.py +4 -0
- classiq/interface/model/handle_binding.py +1 -1
- classiq/interface/model/port_declaration.py +12 -0
- classiq/interface/model/quantum_function_declaration.py +12 -0
- classiq/interface/model/quantum_lambda_function.py +1 -1
- classiq/interface/model/quantum_statement.py +2 -4
- classiq/interface/model/quantum_type.py +102 -3
- classiq/interface/pretty_print/expression_to_qmod.py +3 -17
- classiq/model_expansions/quantum_operations/allocate.py +1 -1
- classiq/model_expansions/quantum_operations/handle_evaluator.py +2 -8
- classiq/open_library/functions/__init__.py +3 -0
- classiq/open_library/functions/lcu.py +2 -2
- classiq/open_library/functions/state_preparation.py +182 -5
- classiq/qmod/builtins/__init__.py +0 -3
- classiq/qmod/builtins/classical_functions.py +0 -28
- classiq/qmod/builtins/enums.py +24 -18
- classiq/qmod/builtins/functions/__init__.py +0 -5
- classiq/qmod/builtins/operations.py +142 -0
- classiq/qmod/builtins/structs.py +0 -11
- classiq/qmod/native/pretty_printer.py +1 -1
- classiq/qmod/pretty_print/expression_to_python.py +3 -6
- classiq/qmod/pretty_print/pretty_printer.py +4 -1
- classiq/qmod/qmod_variable.py +141 -3
- classiq/qmod/semantics/annotation/call_annotation.py +4 -2
- classiq/qmod/semantics/annotation/qstruct_annotator.py +20 -5
- {classiq-0.87.0.dist-info → classiq-0.89.0.dist-info}/METADATA +4 -4
- {classiq-0.87.0.dist-info → classiq-0.89.0.dist-info}/RECORD +69 -81
- classiq/applications/finance/__init__.py +0 -15
- classiq/interface/finance/__init__.py +0 -0
- classiq/interface/finance/finance_modelling_params.py +0 -11
- classiq/interface/finance/function_input.py +0 -102
- classiq/interface/finance/gaussian_model_input.py +0 -50
- classiq/interface/finance/log_normal_model_input.py +0 -40
- classiq/interface/finance/model_input.py +0 -22
- classiq/interface/generator/application_apis/finance_declarations.py +0 -108
- classiq/interface/generator/expressions/enums/__init__.py +0 -0
- classiq/interface/generator/expressions/enums/finance_functions.py +0 -12
- classiq/interface/generator/finance.py +0 -107
- classiq/qmod/builtins/functions/finance.py +0 -34
- {classiq-0.87.0.dist-info → classiq-0.89.0.dist-info}/WHEEL +0 -0
|
@@ -33,7 +33,10 @@ def eval_enum_member(
|
|
|
33
33
|
}
|
|
34
34
|
attr = node.attr
|
|
35
35
|
if attr not in enum_members:
|
|
36
|
-
raise ClassiqExpansionError(
|
|
36
|
+
raise ClassiqExpansionError(
|
|
37
|
+
f"Enum {enum_name} has no member {attr!r}. Available members: "
|
|
38
|
+
f"{', '.join(enum_members.keys())}"
|
|
39
|
+
)
|
|
37
40
|
|
|
38
41
|
expr_val.set_type(node, Enum(name=enum_name))
|
|
39
42
|
expr_val.set_value(node, enum_members[attr])
|
|
@@ -20,7 +20,7 @@ from classiq.evaluators.qmod_node_evaluators.compare_evaluation import (
|
|
|
20
20
|
def eval_struct_instantiation(
|
|
21
21
|
expr_val: QmodAnnotatedExpression, node: ast.Call, decl: StructDeclaration
|
|
22
22
|
) -> None:
|
|
23
|
-
if len(node.args)
|
|
23
|
+
if len(node.args) != 1 or any(kwarg.arg is None for kwarg in node.keywords):
|
|
24
24
|
raise ClassiqExpansionError(
|
|
25
25
|
"Classical structs must be instantiated using keyword arguments"
|
|
26
26
|
)
|
|
@@ -69,7 +69,7 @@ def _eval_slice(expr_val: QmodAnnotatedExpression, node: ast.Subscript) -> None:
|
|
|
69
69
|
subject_type = expr_val.get_type(subject)
|
|
70
70
|
slice_type: QmodType
|
|
71
71
|
if isinstance(subject_type, ClassicalArray):
|
|
72
|
-
if subject_type.
|
|
72
|
+
if subject_type.has_constant_length and (
|
|
73
73
|
(start_val is not None and start_val >= subject_type.length_value)
|
|
74
74
|
or (stop_val is not None and stop_val > subject_type.length_value)
|
|
75
75
|
):
|
|
@@ -93,7 +93,7 @@ def _eval_slice(expr_val: QmodAnnotatedExpression, node: ast.Subscript) -> None:
|
|
|
93
93
|
slice_type = subject_type.get_raw_type()
|
|
94
94
|
elif isinstance(subject_type, QuantumBitvector):
|
|
95
95
|
if start_val is not None and stop_val is not None:
|
|
96
|
-
if subject_type.
|
|
96
|
+
if subject_type.has_constant_length and (
|
|
97
97
|
start_val >= subject_type.length_value
|
|
98
98
|
or stop_val > subject_type.length_value
|
|
99
99
|
):
|
|
@@ -150,7 +150,7 @@ def _eval_subscript(expr_val: QmodAnnotatedExpression, node: ast.Subscript) -> N
|
|
|
150
150
|
if isinstance(subject_type, (ClassicalArray, QuantumBitvector)):
|
|
151
151
|
if (
|
|
152
152
|
sub_val is not None
|
|
153
|
-
and subject_type.
|
|
153
|
+
and subject_type.has_constant_length
|
|
154
154
|
and sub_val >= subject_type.length_value
|
|
155
155
|
):
|
|
156
156
|
raise ClassiqExpansionError("Array index out of range")
|
|
@@ -85,7 +85,7 @@ def array_len(
|
|
|
85
85
|
) -> Optional[int]:
|
|
86
86
|
if isinstance(classical_type, ClassicalTuple):
|
|
87
87
|
return len(classical_type.element_types)
|
|
88
|
-
if classical_type.
|
|
88
|
+
if classical_type.has_constant_length:
|
|
89
89
|
return classical_type.length_value
|
|
90
90
|
return None
|
|
91
91
|
|
|
@@ -73,9 +73,9 @@ def _inject_classical_array_attributes(
|
|
|
73
73
|
if isinstance(to_type, ClassicalArray):
|
|
74
74
|
if isinstance(from_type, ClassicalArray):
|
|
75
75
|
length: Optional[Expression]
|
|
76
|
-
if from_type.
|
|
76
|
+
if from_type.has_constant_length:
|
|
77
77
|
if (
|
|
78
|
-
to_type.
|
|
78
|
+
to_type.has_constant_length
|
|
79
79
|
and from_type.length_value != to_type.length_value
|
|
80
80
|
):
|
|
81
81
|
return None
|
|
@@ -90,7 +90,7 @@ def _inject_classical_array_attributes(
|
|
|
90
90
|
return ClassicalArray(element_type=element_type, length=length)
|
|
91
91
|
if isinstance(from_type, ClassicalTuple):
|
|
92
92
|
if (
|
|
93
|
-
to_type.
|
|
93
|
+
to_type.has_constant_length
|
|
94
94
|
and len(from_type.element_types) != to_type.length_value
|
|
95
95
|
):
|
|
96
96
|
return None
|
|
@@ -103,7 +103,7 @@ def _inject_classical_array_attributes(
|
|
|
103
103
|
return ClassicalTuple(element_types=element_types)
|
|
104
104
|
return None
|
|
105
105
|
if isinstance(from_type, ClassicalArray):
|
|
106
|
-
if from_type.
|
|
106
|
+
if from_type.has_constant_length and from_type.length_value != len(
|
|
107
107
|
to_type.element_types
|
|
108
108
|
):
|
|
109
109
|
return None
|
|
@@ -290,3 +290,41 @@ def inject_quantum_type_attributes_inplace(
|
|
|
290
290
|
to_type.set_fields(updated_type.fields)
|
|
291
291
|
return True
|
|
292
292
|
raise ClassiqInternalExpansionError
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
def validate_quantum_type_attributes(quantum_type: QuantumType) -> None:
|
|
296
|
+
if isinstance(quantum_type, TypeName):
|
|
297
|
+
if len(quantum_type.fields) == 0:
|
|
298
|
+
raise ClassiqExpansionError(
|
|
299
|
+
f"QStruct {quantum_type.name} must have at least one field"
|
|
300
|
+
)
|
|
301
|
+
for field_type in quantum_type.fields.values():
|
|
302
|
+
validate_quantum_type_attributes(field_type)
|
|
303
|
+
return
|
|
304
|
+
if isinstance(quantum_type, QuantumBitvector):
|
|
305
|
+
validate_quantum_type_attributes(quantum_type.element_type)
|
|
306
|
+
if quantum_type.has_constant_length and quantum_type.length_value < 1:
|
|
307
|
+
raise ClassiqExpansionError(
|
|
308
|
+
f"QArray length must be positive, got {quantum_type.length_value}"
|
|
309
|
+
)
|
|
310
|
+
return
|
|
311
|
+
if isinstance(quantum_type, QuantumNumeric):
|
|
312
|
+
if quantum_type.has_size_in_bits and quantum_type.size_in_bits < 1:
|
|
313
|
+
raise ClassiqExpansionError(
|
|
314
|
+
f"QNum size must be positive, got {quantum_type.size_in_bits}"
|
|
315
|
+
)
|
|
316
|
+
if quantum_type.has_fraction_digits:
|
|
317
|
+
if quantum_type.fraction_digits_value < 0:
|
|
318
|
+
raise ClassiqExpansionError(
|
|
319
|
+
f"QNum fraction digits must be positive, got "
|
|
320
|
+
f"{quantum_type.fraction_digits_value}"
|
|
321
|
+
)
|
|
322
|
+
if (
|
|
323
|
+
quantum_type.has_size_in_bits
|
|
324
|
+
and quantum_type.fraction_digits_value > quantum_type.size_in_bits
|
|
325
|
+
):
|
|
326
|
+
raise ClassiqExpansionError(
|
|
327
|
+
f"QNum size ({quantum_type.size_in_bits}) must be greater or "
|
|
328
|
+
f"equals than the fraction digits "
|
|
329
|
+
f"({quantum_type.fraction_digits_value})"
|
|
330
|
+
)
|
|
@@ -21,7 +21,7 @@ def check_signature_match(
|
|
|
21
21
|
) -> None:
|
|
22
22
|
if len(decl_params) != len(op_params):
|
|
23
23
|
raise ClassiqExpansionError(
|
|
24
|
-
f"{location_str} should have {len(decl_params)} parameters, "
|
|
24
|
+
f"{location_str.capitalize()} should have {len(decl_params)} parameters, "
|
|
25
25
|
f"not {len(op_params)}"
|
|
26
26
|
)
|
|
27
27
|
for idx, (decl_param, op_param) in enumerate(zip(decl_params, op_params)):
|
|
@@ -340,6 +340,7 @@ class ExecutionSession:
|
|
|
340
340
|
initial_params: ExecutionParams,
|
|
341
341
|
max_iteration: int,
|
|
342
342
|
quantile: float = 1.0,
|
|
343
|
+
tolerance: Optional[float] = None,
|
|
343
344
|
) -> list[tuple[float, ExecutionParams]]:
|
|
344
345
|
"""
|
|
345
346
|
Minimizes the given cost function using the quantum program.
|
|
@@ -355,6 +356,7 @@ class ExecutionSession:
|
|
|
355
356
|
- The value is either a float or a list of floats.
|
|
356
357
|
max_iteration: The maximum number of iterations for the minimization.
|
|
357
358
|
quantile: The quantile to use for cost estimation.
|
|
359
|
+
tolerance: The tolerance for the minimization.
|
|
358
360
|
Returns:
|
|
359
361
|
A list of tuples, each containing the estimated cost and the corresponding parameters for that iteration.
|
|
360
362
|
`cost` is a float, and `parameters` is a dictionary matching the execution parameter format.
|
|
@@ -365,6 +367,7 @@ class ExecutionSession:
|
|
|
365
367
|
initial_params=initial_params,
|
|
366
368
|
max_iteration=max_iteration,
|
|
367
369
|
quantile=quantile,
|
|
370
|
+
tolerance=tolerance,
|
|
368
371
|
_check_deprecation=False,
|
|
369
372
|
)
|
|
370
373
|
result = job.get_minimization_result(_http_client=self._async_client)
|
|
@@ -379,6 +382,7 @@ class ExecutionSession:
|
|
|
379
382
|
initial_params: ExecutionParams,
|
|
380
383
|
max_iteration: int,
|
|
381
384
|
quantile: float = 1.0,
|
|
385
|
+
tolerance: Optional[float] = None,
|
|
382
386
|
*,
|
|
383
387
|
_check_deprecation: bool = True,
|
|
384
388
|
) -> ExecutionJob:
|
|
@@ -400,6 +404,7 @@ class ExecutionSession:
|
|
|
400
404
|
- The value is either a float or a list of floats.
|
|
401
405
|
max_iteration: The maximum number of iterations for the minimization.
|
|
402
406
|
quantile: The quantile to use for cost estimation.
|
|
407
|
+
tolerance: The tolerance for the minimization.
|
|
403
408
|
|
|
404
409
|
Returns:
|
|
405
410
|
The execution job.
|
|
@@ -424,6 +429,7 @@ class ExecutionSession:
|
|
|
424
429
|
initial_params=_initial_params,
|
|
425
430
|
max_iteration=max_iteration,
|
|
426
431
|
quantile=quantile,
|
|
432
|
+
tolerance=tolerance,
|
|
427
433
|
)
|
|
428
434
|
else:
|
|
429
435
|
_cost_function = self._hamiltonian_to_pauli_operator(cost_function)
|
|
@@ -432,6 +438,7 @@ class ExecutionSession:
|
|
|
432
438
|
initial_params=_initial_params,
|
|
433
439
|
max_iteration=max_iteration,
|
|
434
440
|
quantile=quantile,
|
|
441
|
+
tolerance=tolerance,
|
|
435
442
|
)
|
|
436
443
|
|
|
437
444
|
execution_primitives_input = PrimitivesInput(minimize=minimize)
|
|
@@ -545,10 +552,18 @@ class ExecutionSession:
|
|
|
545
552
|
name: create_qvar_from_quantum_type(reg.quantum_types, name)
|
|
546
553
|
for name, reg in circuit_output_types.items()
|
|
547
554
|
}
|
|
548
|
-
|
|
555
|
+
creator_parameters = inspect.signature(
|
|
556
|
+
qmod_expression_creator
|
|
557
|
+
).parameters.keys()
|
|
558
|
+
for name in creator_parameters:
|
|
549
559
|
if name not in symbolic_output:
|
|
550
560
|
raise ClassiqValueError(
|
|
551
|
-
f"
|
|
561
|
+
f"Expected cost function with parameters {tuple(symbolic_output.keys())} corresponding to the quantum program outputs, but found '{name}'. "
|
|
562
|
+
)
|
|
563
|
+
for name in symbolic_output:
|
|
564
|
+
if name not in creator_parameters:
|
|
565
|
+
raise ClassiqValueError(
|
|
566
|
+
f"Expected cost function with parameter '{name}' corresponding to the quantum program outputs. "
|
|
552
567
|
)
|
|
553
568
|
|
|
554
569
|
qmod_expression = qmod_expression_creator(**symbolic_output)
|
classiq/interface/_version.py
CHANGED
|
@@ -80,7 +80,7 @@ class AnalysisHardwareListParams(AnalysisParams, HardwareListParams):
|
|
|
80
80
|
|
|
81
81
|
|
|
82
82
|
class HardwareParams(pydantic.BaseModel):
|
|
83
|
-
device: PydanticNonEmptyString = pydantic.Field(default=None, description="Devices")
|
|
83
|
+
device: PydanticNonEmptyString = pydantic.Field(default=None, description="Devices") # type: ignore[assignment]
|
|
84
84
|
provider: AnalyzerProviderVendor
|
|
85
85
|
|
|
86
86
|
|
|
@@ -274,7 +274,7 @@ class AzureCredential(BaseSettings):
|
|
|
274
274
|
|
|
275
275
|
def __init__(self, **data: Any) -> None:
|
|
276
276
|
initial_data = {
|
|
277
|
-
field: data[field] for field in data if field in self.model_fields
|
|
277
|
+
field: data[field] for field in data if field in self.__class__.model_fields
|
|
278
278
|
}
|
|
279
279
|
super().__init__(**data)
|
|
280
280
|
for field, value in initial_data.items():
|
|
@@ -6,7 +6,6 @@ from .arithmetic_declarations import * # noqa: F403
|
|
|
6
6
|
from .chemistry_declarations import * # noqa: F403
|
|
7
7
|
from .combinatorial_optimization_declarations import * # noqa: F403
|
|
8
8
|
from .entangler_declarations import * # noqa: F403
|
|
9
|
-
from .finance_declarations import * # noqa: F403
|
|
10
9
|
from .qsvm_declarations import * # noqa: F403
|
|
11
10
|
|
|
12
11
|
populate_builtin_declarations(vars().values())
|
|
@@ -19,7 +19,7 @@ class RegisterArithmeticInfo(HashablePydanticBaseModel):
|
|
|
19
19
|
is_signed: bool = pydantic.Field(default=False)
|
|
20
20
|
fraction_places: pydantic.NonNegativeInt = pydantic.Field(default=0)
|
|
21
21
|
bypass_bounds_validation: bool = pydantic.Field(default=False)
|
|
22
|
-
bounds: PydanticFloatTuple = pydantic.Field(
|
|
22
|
+
bounds: PydanticFloatTuple = pydantic.Field( # type: ignore[assignment]
|
|
23
23
|
default=None,
|
|
24
24
|
validate_default=True,
|
|
25
25
|
)
|
|
@@ -4,8 +4,6 @@ CLASSIQ_BUILTIN_CLASSICAL_FUNCTIONS = {
|
|
|
4
4
|
"hypercube_entangler_graph",
|
|
5
5
|
"grid_entangler_graph",
|
|
6
6
|
"qft_const_adder_phase",
|
|
7
|
-
"log_normal_finance_post_process",
|
|
8
|
-
"gaussian_finance_post_process",
|
|
9
7
|
"molecule_problem_to_hamiltonian",
|
|
10
8
|
"fock_hamiltonian_problem_to_hamiltonian",
|
|
11
9
|
"molecule_ground_state_solution_post_process",
|
|
@@ -33,7 +33,6 @@ from classiq.interface.generator.entangler_params import (
|
|
|
33
33
|
HypercubeEntangler,
|
|
34
34
|
TwoDimensionalEntangler,
|
|
35
35
|
)
|
|
36
|
-
from classiq.interface.generator.finance import Finance, FinanceModels, FinancePayoff
|
|
37
36
|
from classiq.interface.generator.function_param_library import FunctionParamLibrary
|
|
38
37
|
from classiq.interface.generator.hadamard_transform import HadamardTransform
|
|
39
38
|
from classiq.interface.generator.hamiltonian_evolution.exponentiation import (
|
|
@@ -106,9 +105,6 @@ function_param_library: FunctionParamLibrary = FunctionParamLibrary(
|
|
|
106
105
|
CyclicShift,
|
|
107
106
|
Modulo,
|
|
108
107
|
TwoDimensionalEntangler,
|
|
109
|
-
Finance,
|
|
110
|
-
FinanceModels,
|
|
111
|
-
FinancePayoff,
|
|
112
108
|
HypercubeEntangler,
|
|
113
109
|
GridEntangler,
|
|
114
110
|
Mcx,
|
|
@@ -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"]
|
|
@@ -144,6 +145,14 @@ class ClassicalArray(ClassicalType):
|
|
|
144
145
|
def has_length(self) -> bool:
|
|
145
146
|
return self.length is not None and self.length.is_evaluated()
|
|
146
147
|
|
|
148
|
+
@property
|
|
149
|
+
def has_constant_length(self) -> bool:
|
|
150
|
+
return (
|
|
151
|
+
self.length is not None
|
|
152
|
+
and self.length.is_evaluated()
|
|
153
|
+
and self.length.is_constant()
|
|
154
|
+
)
|
|
155
|
+
|
|
147
156
|
@property
|
|
148
157
|
def length_value(self) -> int:
|
|
149
158
|
if not self.has_length:
|
|
@@ -195,6 +204,18 @@ class ClassicalArray(ClassicalType):
|
|
|
195
204
|
def raw_qmod_type_name(self) -> str:
|
|
196
205
|
return "CArray"
|
|
197
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
|
+
|
|
198
219
|
|
|
199
220
|
class ClassicalTuple(ClassicalType):
|
|
200
221
|
kind: Literal["tuple"]
|
|
@@ -265,6 +286,14 @@ class ClassicalTuple(ClassicalType):
|
|
|
265
286
|
def raw_qmod_type_name(self) -> str:
|
|
266
287
|
return "CArray"
|
|
267
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
|
+
|
|
268
297
|
|
|
269
298
|
class OpaqueHandle(ClassicalType):
|
|
270
299
|
pass
|
|
@@ -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()
|
|
@@ -101,6 +101,12 @@ class TypeName(ClassicalType, QuantumType):
|
|
|
101
101
|
field_type.is_evaluated for field_type in self.fields.values()
|
|
102
102
|
)
|
|
103
103
|
|
|
104
|
+
@property
|
|
105
|
+
def is_constant(self) -> bool:
|
|
106
|
+
return self.has_fields and all(
|
|
107
|
+
field_type.is_constant for field_type in self.fields.values()
|
|
108
|
+
)
|
|
109
|
+
|
|
104
110
|
@property
|
|
105
111
|
def has_classical_struct_decl(self) -> bool:
|
|
106
112
|
return self._classical_struct_decl is not None
|
|
@@ -183,6 +189,31 @@ class TypeName(ClassicalType, QuantumType):
|
|
|
183
189
|
field_type.minimal_size_in_bits for field_type in self.fields.values()
|
|
184
190
|
)
|
|
185
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
|
+
|
|
186
217
|
|
|
187
218
|
class Enum(TypeName):
|
|
188
219
|
pass
|
|
@@ -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,
|
|
@@ -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. "
|
|
@@ -57,11 +57,15 @@ EXTRA_TWO_QUBIT_GATES: BasisGates = frozenset(
|
|
|
57
57
|
)
|
|
58
58
|
)
|
|
59
59
|
|
|
60
|
+
NON_UNITARY_GATES: BasisGates = frozenset(("if_else",))
|
|
61
|
+
|
|
60
62
|
TWO_QUBIT_GATES = BASIC_TWO_QUBIT_GATES | EXTRA_TWO_QUBIT_GATES
|
|
61
63
|
|
|
62
64
|
THREE_QUBIT_GATES: BasisGates = frozenset(("ccx", "cswap"))
|
|
63
65
|
DEFAULT_BASIS_GATES: BasisGates = SINGLE_QUBIT_GATES | BASIC_TWO_QUBIT_GATES
|
|
64
|
-
ALL_GATES: BasisGates =
|
|
66
|
+
ALL_GATES: BasisGates = (
|
|
67
|
+
SINGLE_QUBIT_GATES | TWO_QUBIT_GATES | THREE_QUBIT_GATES | NON_UNITARY_GATES
|
|
68
|
+
)
|
|
65
69
|
|
|
66
70
|
ROUTING_TWO_QUBIT_BASIS_GATES: BasisGates = frozenset(
|
|
67
71
|
("cx", "ecr", "rzx", "ryy", "rxx", "rzz", "cy", "cz", "cp", "swap")
|
|
@@ -132,13 +132,6 @@ class FermionMapping(IntEnum):
|
|
|
132
132
|
FAST_BRAVYI_KITAEV = 3
|
|
133
133
|
|
|
134
134
|
|
|
135
|
-
class FinanceFunctionType(IntEnum):
|
|
136
|
-
VAR = 0
|
|
137
|
-
SHORTFALL = 1
|
|
138
|
-
X_SQUARE = 2
|
|
139
|
-
EUROPEAN_CALL_OPTION = 3
|
|
140
|
-
|
|
141
|
-
|
|
142
135
|
class LadderOperator(IntEnum):
|
|
143
136
|
PLUS = 0
|
|
144
137
|
MINUS = 1
|
|
@@ -171,7 +164,6 @@ class QSVMFeatureMapEntanglement(IntEnum):
|
|
|
171
164
|
__all__ = [
|
|
172
165
|
"Element",
|
|
173
166
|
"FermionMapping",
|
|
174
|
-
"FinanceFunctionType",
|
|
175
167
|
"LadderOperator",
|
|
176
168
|
"Optimizer",
|
|
177
169
|
"Pauli",
|
|
@@ -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(
|
|
@@ -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()
|
|
@@ -207,9 +207,9 @@ class Operation(pydantic.BaseModel):
|
|
|
207
207
|
|
|
208
208
|
|
|
209
209
|
class ProgramVisualModel(VersionedModel):
|
|
210
|
-
main_operation: Operation = pydantic.Field(default=None)
|
|
210
|
+
main_operation: Operation = pydantic.Field(default=None) # type: ignore[assignment]
|
|
211
211
|
id_to_operations: dict[int, Operation] = pydantic.Field(default_factory=dict)
|
|
212
|
-
main_operation_id: int = pydantic.Field(default=None)
|
|
212
|
+
main_operation_id: int = pydantic.Field(default=None) # type: ignore[assignment]
|
|
213
213
|
program_data: ProgramData
|
|
214
214
|
|
|
215
215
|
@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)
|
|
@@ -3,6 +3,8 @@ import operator
|
|
|
3
3
|
from collections.abc import Mapping
|
|
4
4
|
from typing import TYPE_CHECKING, Literal
|
|
5
5
|
|
|
6
|
+
import pydantic
|
|
7
|
+
|
|
6
8
|
from classiq.interface.ast_node import ASTNodeType, reset_lists
|
|
7
9
|
from classiq.interface.generator.expressions.expression import Expression
|
|
8
10
|
from classiq.interface.model.handle_binding import ConcreteHandleBinding, HandleBinding
|
|
@@ -18,6 +20,9 @@ class ClassicalIf(QuantumOperation):
|
|
|
18
20
|
condition: Expression
|
|
19
21
|
then: "StatementBlock"
|
|
20
22
|
else_: "StatementBlock"
|
|
23
|
+
_condition_wiring_inouts: dict[str, HandleBinding] = pydantic.PrivateAttr(
|
|
24
|
+
default_factory=dict
|
|
25
|
+
)
|
|
21
26
|
|
|
22
27
|
def _as_back_ref(self: ASTNodeType) -> ASTNodeType:
|
|
23
28
|
return reset_lists(self, ["then", "else_"])
|
|
@@ -40,14 +45,17 @@ class ClassicalIf(QuantumOperation):
|
|
|
40
45
|
|
|
41
46
|
@property
|
|
42
47
|
def wiring_inouts(self) -> Mapping[str, ConcreteHandleBinding]:
|
|
43
|
-
return
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
return (
|
|
49
|
+
functools.reduce(
|
|
50
|
+
operator.ior,
|
|
51
|
+
(
|
|
52
|
+
op.wiring_inouts
|
|
53
|
+
for op in (*self.then, *self.else_)
|
|
54
|
+
if isinstance(op, QuantumOperation)
|
|
55
|
+
),
|
|
56
|
+
dict(),
|
|
57
|
+
)
|
|
58
|
+
| self._condition_wiring_inouts
|
|
51
59
|
)
|
|
52
60
|
|
|
53
61
|
@property
|
|
@@ -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:
|