classiq 0.60.1__py3-none-any.whl → 0.62.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- classiq/__init__.py +2 -0
- classiq/_internals/client.py +6 -1
- classiq/applications/__init__.py +1 -1
- classiq/applications/chemistry/__init__.py +7 -7
- classiq/applications/chemistry/chemistry_model_constructor.py +17 -6
- classiq/applications/combinatorial_helpers/optimization_model.py +9 -2
- classiq/applications/combinatorial_helpers/pyomo_utils.py +60 -9
- classiq/applications/combinatorial_optimization/__init__.py +7 -1
- classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +2 -0
- classiq/applications/combinatorial_optimization/combinatorial_problem.py +230 -0
- classiq/applications/finance/finance_model_constructor.py +6 -6
- classiq/applications/grover/grover_model_constructor.py +3 -0
- classiq/applications/libraries/qmci_library.py +1 -10
- classiq/applications/qnn/__init__.py +1 -1
- classiq/applications/qnn/datasets/__init__.py +8 -8
- classiq/applications/qsvm/qsvm.py +1 -1
- classiq/execution/__init__.py +0 -2
- classiq/execution/execution_session.py +6 -0
- classiq/execution/jobs.py +9 -1
- classiq/executor.py +1 -1
- classiq/interface/_version.py +1 -1
- classiq/interface/backend/backend_preferences.py +33 -15
- classiq/interface/backend/quantum_backend_providers.py +3 -1
- classiq/interface/executor/execution_preferences.py +1 -1
- classiq/interface/generator/application_apis/chemistry_declarations.py +1 -1
- classiq/interface/generator/application_apis/finance_declarations.py +2 -2
- classiq/interface/generator/arith/arithmetic.py +16 -1
- classiq/interface/generator/arith/arithmetic_expression_validator.py +4 -3
- classiq/interface/generator/copy.py +47 -0
- classiq/interface/generator/expressions/expression_constants.py +3 -0
- classiq/interface/generator/function_param_list_without_self_reference.py +2 -0
- classiq/interface/generator/generated_circuit_data.py +58 -20
- classiq/interface/generator/model/__init__.py +1 -1
- classiq/interface/generator/model/preferences/preferences.py +1 -1
- classiq/interface/generator/model/quantum_register.py +3 -3
- classiq/interface/generator/standard_gates/controlled_standard_gates.py +20 -32
- classiq/interface/generator/types/compilation_metadata.py +2 -1
- classiq/interface/ide/visual_model.py +1 -0
- classiq/interface/interface_version.py +1 -1
- classiq/interface/model/model.py +2 -3
- classiq/interface/model/quantum_function_call.py +4 -7
- classiq/interface/model/quantum_function_declaration.py +7 -0
- classiq/interface/model/quantum_lambda_function.py +10 -1
- classiq/interface/model/quantum_type.py +3 -1
- classiq/model_expansions/atomic_expression_functions_defs.py +3 -1
- classiq/model_expansions/capturing/captured_vars.py +36 -17
- classiq/model_expansions/capturing/mangling_utils.py +23 -15
- classiq/model_expansions/closure.py +6 -9
- classiq/model_expansions/evaluators/arg_type_match.py +7 -7
- classiq/model_expansions/expression_evaluator.py +5 -2
- classiq/model_expansions/function_builder.py +26 -4
- classiq/model_expansions/generative_functions.py +13 -91
- classiq/model_expansions/interpreter.py +75 -46
- classiq/model_expansions/quantum_operations/call_emitter.py +42 -29
- classiq/model_expansions/quantum_operations/classicalif.py +1 -1
- classiq/model_expansions/quantum_operations/control.py +5 -31
- classiq/model_expansions/quantum_operations/emitter.py +29 -17
- classiq/model_expansions/quantum_operations/expression_operation.py +3 -5
- classiq/model_expansions/quantum_operations/inplace_binary_operation.py +57 -15
- classiq/model_expansions/quantum_operations/invert.py +1 -6
- classiq/model_expansions/quantum_operations/phase.py +2 -5
- classiq/model_expansions/quantum_operations/power.py +0 -4
- classiq/model_expansions/quantum_operations/quantum_assignment_operation.py +19 -30
- classiq/model_expansions/quantum_operations/quantum_function_call.py +4 -2
- classiq/model_expansions/quantum_operations/shallow_emitter.py +161 -0
- classiq/model_expansions/quantum_operations/within_apply.py +0 -14
- classiq/model_expansions/scope.py +12 -16
- classiq/model_expansions/scope_initialization.py +0 -11
- classiq/model_expansions/sympy_conversion/expression_to_sympy.py +7 -0
- classiq/model_expansions/sympy_conversion/sympy_to_python.py +12 -2
- classiq/model_expansions/transformers/ast_renamer.py +26 -0
- classiq/model_expansions/transformers/var_splitter.py +11 -12
- classiq/model_expansions/visitors/variable_references.py +20 -12
- classiq/qmod/builtins/classical_execution_primitives.py +6 -6
- classiq/qmod/builtins/classical_functions.py +10 -10
- classiq/qmod/builtins/functions/__init__.py +89 -103
- classiq/qmod/builtins/functions/amplitude_estimation.py +1 -1
- classiq/qmod/builtins/functions/arithmetic.py +1 -1
- classiq/qmod/builtins/functions/discrete_sine_cosine_transform.py +6 -6
- classiq/qmod/builtins/functions/grover.py +5 -5
- classiq/qmod/builtins/functions/hea.py +1 -1
- classiq/qmod/builtins/functions/linear_pauli_rotation.py +2 -2
- classiq/qmod/builtins/functions/modular_exponentiation.py +8 -8
- classiq/qmod/builtins/functions/operators.py +1 -1
- classiq/qmod/builtins/functions/qaoa_penalty.py +5 -5
- classiq/qmod/builtins/functions/qft_functions.py +2 -2
- classiq/qmod/builtins/functions/qpe.py +9 -12
- classiq/qmod/builtins/functions/qsvt.py +177 -15
- classiq/qmod/builtins/functions/state_preparation.py +9 -9
- classiq/qmod/builtins/functions/swap_test.py +1 -1
- classiq/qmod/builtins/functions/utility_functions.py +2 -2
- classiq/qmod/builtins/functions/variational.py +2 -2
- classiq/qmod/builtins/operations.py +22 -83
- classiq/qmod/builtins/structs.py +9 -9
- classiq/qmod/native/pretty_printer.py +17 -19
- classiq/qmod/pretty_print/pretty_printer.py +9 -6
- classiq/qmod/python_classical_type.py +1 -5
- classiq/qmod/qmod_variable.py +2 -5
- classiq/qmod/quantum_expandable.py +20 -5
- classiq/qmod/quantum_function.py +23 -10
- classiq/qmod/semantics/static_semantics_visitor.py +34 -16
- classiq/qmod/semantics/validation/func_call_validation.py +9 -5
- classiq/qmod/semantics/validation/function_name_collisions_validation.py +23 -0
- classiq/qmod/symbolic.py +47 -47
- {classiq-0.60.1.dist-info → classiq-0.62.0.dist-info}/METADATA +2 -1
- {classiq-0.60.1.dist-info → classiq-0.62.0.dist-info}/RECORD +107 -103
- classiq/execution/qaoa.py +0 -86
- {classiq-0.60.1.dist-info → classiq-0.62.0.dist-info}/WHEEL +0 -0
classiq/execution/jobs.py
CHANGED
@@ -112,7 +112,15 @@ class ExecutionJob:
|
|
112
112
|
)
|
113
113
|
return cls(details)
|
114
114
|
|
115
|
-
|
115
|
+
# `syncify_function` doesn't work well for class methods, so I wrote `from_id`
|
116
|
+
# explicitly
|
117
|
+
@classmethod
|
118
|
+
def from_id(
|
119
|
+
cls,
|
120
|
+
id: str,
|
121
|
+
_http_client: Optional[httpx.AsyncClient] = None,
|
122
|
+
) -> "ExecutionJob":
|
123
|
+
return syncify_function(cls.from_id_async)(id, _http_client=_http_client)
|
116
124
|
|
117
125
|
@property
|
118
126
|
def _job_id(self) -> JobID:
|
classiq/executor.py
CHANGED
classiq/interface/_version.py
CHANGED
@@ -161,6 +161,20 @@ class ClassiqBackendPreferences(BackendPreferences):
|
|
161
161
|
def is_nvidia_backend(self) -> bool:
|
162
162
|
return self.backend_name in list(ClassiqNvidiaBackendNames)
|
163
163
|
|
164
|
+
# CAD-25390
|
165
|
+
@pydantic.field_validator("backend_name")
|
166
|
+
@classmethod
|
167
|
+
def _validate_nvidia_name_backwards_compatibility(cls, backend_name: str) -> str:
|
168
|
+
if backend_name == "nvidia_state_vector_simulator":
|
169
|
+
warnings.warn(
|
170
|
+
"The name 'nvidia_state_vector_simulator' is deprecated and "
|
171
|
+
"will be removed soon, no earlier than January 12th 2025. "
|
172
|
+
"Please use ClassiqNvidiaBackendNames.SIMULATOR instead",
|
173
|
+
ClassiqDeprecationWarning,
|
174
|
+
stacklevel=2,
|
175
|
+
)
|
176
|
+
return backend_name
|
177
|
+
|
164
178
|
|
165
179
|
class AwsBackendPreferences(BackendPreferences):
|
166
180
|
"""
|
@@ -196,13 +210,17 @@ class AwsBackendPreferences(BackendPreferences):
|
|
196
210
|
backend_service_provider: ProviderTypeVendor.AMAZON_BRAKET = pydantic.Field(
|
197
211
|
default=ProviderVendor.AMAZON_BRAKET
|
198
212
|
)
|
199
|
-
aws_role_arn: pydantic_backend.PydanticAwsRoleArn = pydantic.Field(
|
213
|
+
aws_role_arn: Optional[pydantic_backend.PydanticAwsRoleArn] = pydantic.Field(
|
200
214
|
description="ARN of the role to be assumed for execution on your Braket account."
|
201
215
|
)
|
202
|
-
s3_bucket_name: str = pydantic.Field(description="S3 Bucket Name")
|
203
|
-
s3_folder: pydantic_backend.PydanticS3BucketKey = pydantic.Field(
|
216
|
+
s3_bucket_name: Optional[str] = pydantic.Field(description="S3 Bucket Name")
|
217
|
+
s3_folder: Optional[pydantic_backend.PydanticS3BucketKey] = pydantic.Field(
|
204
218
|
description="S3 Folder Path Within The S3 Bucket"
|
205
219
|
)
|
220
|
+
run_through_classiq: bool = pydantic.Field(
|
221
|
+
default=False,
|
222
|
+
description="Run through Classiq's credentials while using user's allocated budget.",
|
223
|
+
)
|
206
224
|
|
207
225
|
@pydantic.field_validator("s3_bucket_name", mode="before")
|
208
226
|
@classmethod
|
@@ -513,25 +531,25 @@ BackendPreferencesTypes = Union[
|
|
513
531
|
]
|
514
532
|
|
515
533
|
__all__ = [
|
534
|
+
"AQTBackendPreferences",
|
535
|
+
"AliceBobBackendNames",
|
536
|
+
"AliceBobBackendPreferences",
|
537
|
+
"AmazonBraketBackendNames",
|
538
|
+
"AwsBackendPreferences",
|
516
539
|
"AzureBackendPreferences",
|
517
540
|
"AzureCredential",
|
518
541
|
"AzureQuantumBackendNames",
|
519
542
|
"ClassiqBackendPreferences",
|
543
|
+
"ClassiqNvidiaBackendNames",
|
520
544
|
"ClassiqSimulatorBackendNames",
|
545
|
+
"GCPBackendPreferences",
|
521
546
|
"IBMBackendPreferences",
|
522
547
|
"IBMBackendProvider",
|
523
|
-
"
|
524
|
-
"AmazonBraketBackendNames",
|
525
|
-
"IonqBackendPreferences",
|
526
|
-
"IonqBackendNames",
|
527
|
-
"ClassiqNvidiaBackendNames",
|
548
|
+
"IQCCBackendPreferences",
|
528
549
|
"IntelBackendNames",
|
529
|
-
"GCPBackendPreferences",
|
530
|
-
"AliceBobBackendPreferences",
|
531
|
-
"AliceBobBackendNames",
|
532
|
-
"OQCBackendPreferences",
|
533
|
-
"OQCBackendNames",
|
534
550
|
"IntelBackendPreferences",
|
535
|
-
"
|
536
|
-
"
|
551
|
+
"IonqBackendNames",
|
552
|
+
"IonqBackendPreferences",
|
553
|
+
"OQCBackendNames",
|
554
|
+
"OQCBackendPreferences",
|
537
555
|
]
|
@@ -170,7 +170,8 @@ class ClassiqNvidiaBackendNames(StrEnum):
|
|
170
170
|
Classiq's Nvidia simulator backend names.
|
171
171
|
"""
|
172
172
|
|
173
|
-
SIMULATOR = "
|
173
|
+
SIMULATOR = "nvidia_simulator"
|
174
|
+
SIMULATOR_STATEVECTOR = "nvidia_simulator_statevector"
|
174
175
|
|
175
176
|
|
176
177
|
class IntelBackendNames(StrEnum):
|
@@ -186,6 +187,7 @@ class GoogleNvidiaBackendNames(StrEnum):
|
|
186
187
|
"""
|
187
188
|
|
188
189
|
CUQUANTUM = "cuquantum"
|
190
|
+
CUQUANTUM_STATEVECTOR = "cuquantum_statevector"
|
189
191
|
|
190
192
|
|
191
193
|
class AliceBobBackendNames(StrEnum):
|
@@ -61,7 +61,7 @@ MOLECULE_GROUND_STATE_SOLUTION_POST_PROCESS = ClassicalFunctionDeclaration(
|
|
61
61
|
)
|
62
62
|
|
63
63
|
__all__ = [
|
64
|
-
"MOLECULE_PROBLEM_TO_HAMILTONIAN",
|
65
64
|
"FOCK_HAMILTONIAN_PROBLEM_TO_HAMILTONIAN",
|
66
65
|
"MOLECULE_GROUND_STATE_SOLUTION_POST_PROCESS",
|
66
|
+
"MOLECULE_PROBLEM_TO_HAMILTONIAN",
|
67
67
|
]
|
@@ -98,8 +98,8 @@ GAUSSIAN_FINANCE_POST_PROCESS = ClassicalFunctionDeclaration(
|
|
98
98
|
)
|
99
99
|
|
100
100
|
__all__ = [
|
101
|
-
"LOG_NORMAL_FINANCE_FUNCTION",
|
102
101
|
"GAUSSIAN_FINANCE_FUNCTION",
|
103
|
-
"LOG_NORMAL_FINANCE_POST_PROCESS",
|
104
102
|
"GAUSSIAN_FINANCE_POST_PROCESS",
|
103
|
+
"LOG_NORMAL_FINANCE_FUNCTION",
|
104
|
+
"LOG_NORMAL_FINANCE_POST_PROCESS",
|
105
105
|
]
|
@@ -9,6 +9,9 @@ from classiq.interface.generator.arith import arithmetic_expression_parser
|
|
9
9
|
from classiq.interface.generator.arith.arithmetic_expression_abc import (
|
10
10
|
ArithmeticExpressionABC,
|
11
11
|
)
|
12
|
+
from classiq.interface.generator.arith.arithmetic_expression_validator import (
|
13
|
+
is_constant,
|
14
|
+
)
|
12
15
|
from classiq.interface.generator.arith.arithmetic_param_getters import (
|
13
16
|
id2op,
|
14
17
|
operation_allows_target,
|
@@ -17,7 +20,9 @@ from classiq.interface.generator.arith.arithmetic_result_builder import (
|
|
17
20
|
ArithmeticResultBuilder,
|
18
21
|
)
|
19
22
|
from classiq.interface.generator.arith.register_user_input import RegisterArithmeticInfo
|
23
|
+
from classiq.interface.generator.expressions.expression import Expression
|
20
24
|
from classiq.interface.model.quantum_type import (
|
25
|
+
QuantumNumeric,
|
21
26
|
QuantumType,
|
22
27
|
quantum_var_to_register,
|
23
28
|
register_info_to_quantum_type,
|
@@ -28,6 +33,10 @@ ARITHMETIC_EXPRESSION_RESULT_NAME: Final[str] = "expression_result"
|
|
28
33
|
ARITHMETIC_EXPRESSION_GARBAGE_NAME: Final[str] = "expression_garbage"
|
29
34
|
|
30
35
|
|
36
|
+
def is_zero(expr: str) -> bool:
|
37
|
+
return is_constant(expr) and float(expr) == 0
|
38
|
+
|
39
|
+
|
31
40
|
class Arithmetic(ArithmeticExpressionABC):
|
32
41
|
target: Optional[RegisterArithmeticInfo] = None
|
33
42
|
inputs_to_save: set[str] = pydantic.Field(default_factory=set)
|
@@ -99,7 +108,13 @@ def get_arithmetic_params(
|
|
99
108
|
|
100
109
|
def compute_arithmetic_result_type(
|
101
110
|
expr_str: str, var_types: dict[str, QuantumType], machine_precision: int
|
102
|
-
) ->
|
111
|
+
) -> QuantumNumeric:
|
112
|
+
if is_zero(expr_str):
|
113
|
+
return QuantumNumeric(
|
114
|
+
size=Expression(expr="1"),
|
115
|
+
is_signed=Expression(expr="False"),
|
116
|
+
fraction_digits=Expression(expr="0"),
|
117
|
+
)
|
103
118
|
arith_param = get_arithmetic_params(expr_str, var_types, machine_precision)
|
104
119
|
return register_info_to_quantum_type(
|
105
120
|
arith_param.outputs[ARITHMETIC_EXPRESSION_RESULT_NAME]
|
@@ -3,6 +3,7 @@ import re
|
|
3
3
|
from _ast import AST
|
4
4
|
from typing import Any, Optional, Union
|
5
5
|
|
6
|
+
from sympy import Expr
|
6
7
|
from typing_extensions import TypeAlias, get_args
|
7
8
|
|
8
9
|
from classiq.interface.exceptions import ClassiqArithmeticError, ClassiqValueError
|
@@ -54,11 +55,11 @@ SupportedNodesTypes = Union[
|
|
54
55
|
DEFAULT_SUPPORTED_NODE_TYPES = get_args(SupportedNodesTypes)
|
55
56
|
|
56
57
|
|
57
|
-
def
|
58
|
+
def is_constant(expr: Union[str, Expr]) -> bool:
|
58
59
|
try:
|
59
60
|
float(expr)
|
60
61
|
return True
|
61
|
-
except ValueError:
|
62
|
+
except (ValueError, TypeError):
|
62
63
|
return False
|
63
64
|
|
64
65
|
|
@@ -94,7 +95,7 @@ class ExpressionValidator(ast.NodeVisitor):
|
|
94
95
|
@staticmethod
|
95
96
|
def _get_adjusted_expression(expression: str) -> str:
|
96
97
|
# This works around the simplification of the trivial expressions such as a + 0, 1 * a, etc.
|
97
|
-
if IDENITIFIER_REGEX.fullmatch(expression) or
|
98
|
+
if IDENITIFIER_REGEX.fullmatch(expression) or is_constant(expression):
|
98
99
|
return f"0 + {expression}"
|
99
100
|
return expression
|
100
101
|
|
@@ -0,0 +1,47 @@
|
|
1
|
+
from typing import Optional
|
2
|
+
|
3
|
+
import pydantic
|
4
|
+
|
5
|
+
from classiq.interface.generator.arith import argument_utils
|
6
|
+
from classiq.interface.generator.arith.register_user_input import RegisterArithmeticInfo
|
7
|
+
from classiq.interface.generator.function_params import FunctionParams
|
8
|
+
|
9
|
+
|
10
|
+
class Copy(FunctionParams):
|
11
|
+
source: argument_utils.RegisterOrConst
|
12
|
+
target: RegisterArithmeticInfo
|
13
|
+
output_size: Optional[pydantic.PositiveInt] = pydantic.Field(default=None)
|
14
|
+
|
15
|
+
@property
|
16
|
+
def source_size(self) -> int:
|
17
|
+
return argument_utils.size(self.source)
|
18
|
+
|
19
|
+
@property
|
20
|
+
def source_reg_size(self) -> int:
|
21
|
+
return (
|
22
|
+
self.source.size if isinstance(self.source, RegisterArithmeticInfo) else 0
|
23
|
+
)
|
24
|
+
|
25
|
+
@property
|
26
|
+
def source_fraction_places(self) -> int:
|
27
|
+
return argument_utils.fraction_places(self.source)
|
28
|
+
|
29
|
+
@property
|
30
|
+
def offset(self) -> int:
|
31
|
+
return self.target.fraction_places - self.source_fraction_places
|
32
|
+
|
33
|
+
@property
|
34
|
+
def source_name(self) -> str:
|
35
|
+
return "source"
|
36
|
+
|
37
|
+
@property
|
38
|
+
def target_name(self) -> str:
|
39
|
+
return "target"
|
40
|
+
|
41
|
+
def _create_ios(self) -> None:
|
42
|
+
self._inputs = {
|
43
|
+
self.target_name: self.target,
|
44
|
+
}
|
45
|
+
if isinstance(self.source, RegisterArithmeticInfo):
|
46
|
+
self._inputs[self.source_name] = self.source
|
47
|
+
self._outputs = {**self._inputs}
|
@@ -20,3 +20,6 @@ BOOLEAN_LITERALS = {"True", "False"}
|
|
20
20
|
FORBIDDEN_LITERALS: set[str] = set(keyword.kwlist) - SUPPORTED_FUNC_NAMES
|
21
21
|
CPARAM_EXECUTION_SUFFIX: Final[str] = "_param"
|
22
22
|
RESERVED_EXPRESSIONS: frozenset[str] = frozenset({"i"})
|
23
|
+
CPARAM_EXECUTION_SUFFIX_PATTERN = (
|
24
|
+
rf"({CPARAM_EXECUTION_SUFFIX}|^({'|'.join(RESERVED_EXPRESSIONS)}))(_\d+)*$"
|
25
|
+
)
|
@@ -28,6 +28,7 @@ from classiq.interface.generator.arith.unary_ops import BitwiseInvert, Negation,
|
|
28
28
|
from classiq.interface.generator.commuting_pauli_exponentiation import (
|
29
29
|
CommutingPauliExponentiation,
|
30
30
|
)
|
31
|
+
from classiq.interface.generator.copy import Copy
|
31
32
|
from classiq.interface.generator.entangler_params import (
|
32
33
|
GridEntangler,
|
33
34
|
HypercubeEntangler,
|
@@ -148,6 +149,7 @@ function_param_library_without_self_reference: FunctionParamLibrary = (
|
|
148
149
|
PiecewiseLinearAmplitudeLoading,
|
149
150
|
PiecewiseLinearRotationAmplitudeLoading,
|
150
151
|
HadamardTransform,
|
152
|
+
Copy,
|
151
153
|
},
|
152
154
|
standard_gate_function_param_library.param_list,
|
153
155
|
oracle_function_param_library.param_list,
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import logging
|
2
|
-
from typing import
|
2
|
+
from typing import Literal, Optional, Union
|
3
3
|
|
4
4
|
import pydantic
|
5
5
|
from pydantic import ConfigDict
|
@@ -12,6 +12,12 @@ from classiq.interface.generator.synthesis_metadata.synthesis_execution_data imp
|
|
12
12
|
ExecutionData,
|
13
13
|
)
|
14
14
|
|
15
|
+
from classiq.model_expansions.capturing.mangling_utils import (
|
16
|
+
demangle_capture_name,
|
17
|
+
demangle_name,
|
18
|
+
is_captured_var_name,
|
19
|
+
)
|
20
|
+
|
15
21
|
_logger = logging.getLogger(__name__)
|
16
22
|
ParameterName = str
|
17
23
|
IOQubitMapping: TypeAlias = dict[str, tuple[int, ...]]
|
@@ -52,6 +58,16 @@ class GeneratedRegister(pydantic.BaseModel):
|
|
52
58
|
def width(self) -> int:
|
53
59
|
return len(self)
|
54
60
|
|
61
|
+
@property
|
62
|
+
def is_captured(self) -> bool:
|
63
|
+
return is_captured_var_name(self.name)
|
64
|
+
|
65
|
+
@staticmethod
|
66
|
+
def demangle_name(name: str) -> str:
|
67
|
+
if is_captured_var_name(name):
|
68
|
+
return demangle_capture_name(name)
|
69
|
+
return demangle_name(name)
|
70
|
+
|
55
71
|
|
56
72
|
class GeneratedFunction(pydantic.BaseModel):
|
57
73
|
name: str
|
@@ -157,32 +173,54 @@ class FunctionDebugInfoInterface(pydantic.BaseModel):
|
|
157
173
|
for key, value in parameters.items()
|
158
174
|
]
|
159
175
|
|
160
|
-
def
|
161
|
-
for key, value in kwargs.items():
|
162
|
-
setattr(self, key, value)
|
163
|
-
|
164
|
-
def propagate_absolute_qubits(self) -> None:
|
176
|
+
def propagate_absolute_qubits(self) -> "FunctionDebugInfoInterface":
|
165
177
|
if self.absolute_qubits is None:
|
166
|
-
return
|
167
|
-
|
168
|
-
|
169
|
-
register.
|
170
|
-
|
171
|
-
|
178
|
+
return self
|
179
|
+
|
180
|
+
updated_registers = [
|
181
|
+
register.model_copy(
|
182
|
+
update=dict(
|
183
|
+
qubit_indexes_absolute=list(
|
184
|
+
_get_absolute_from_relative(
|
185
|
+
self.absolute_qubits, tuple(register.qubit_indexes_relative)
|
186
|
+
)
|
187
|
+
)
|
172
188
|
)
|
173
189
|
)
|
190
|
+
for register in self.registers
|
191
|
+
]
|
192
|
+
updated_generated_function = (
|
193
|
+
self.generated_function.model_copy(update=dict(registers=updated_registers))
|
194
|
+
if self.generated_function
|
195
|
+
else None
|
196
|
+
)
|
174
197
|
|
198
|
+
updated_children: list[FunctionDebugInfoInterface] = []
|
175
199
|
for child in self.children:
|
176
|
-
|
177
|
-
|
200
|
+
updated_child = child.model_copy(
|
201
|
+
update=dict(
|
202
|
+
absolute_qubits=_get_absolute_from_relative(
|
203
|
+
self.absolute_qubits, child.relative_qubits
|
204
|
+
)
|
205
|
+
)
|
178
206
|
)
|
179
|
-
|
207
|
+
updated_children.append(updated_child.propagate_absolute_qubits())
|
180
208
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
209
|
+
return self.model_copy(
|
210
|
+
update=dict(
|
211
|
+
generated_function=updated_generated_function,
|
212
|
+
children=updated_children,
|
213
|
+
)
|
214
|
+
)
|
215
|
+
|
216
|
+
def inverse(self) -> "FunctionDebugInfoInterface":
|
217
|
+
inverted_children = [child.inverse() for child in self.children[::-1]]
|
218
|
+
return self.model_copy(
|
219
|
+
update=dict(
|
220
|
+
is_inverse=not self.is_inverse,
|
221
|
+
children=inverted_children,
|
222
|
+
)
|
223
|
+
)
|
186
224
|
|
187
225
|
|
188
226
|
def _get_absolute_from_relative(
|
@@ -156,7 +156,7 @@ class Preferences(pydantic.BaseModel, extra="forbid"):
|
|
156
156
|
)
|
157
157
|
synthesize_all_separately: bool = pydantic.Field(
|
158
158
|
default=False,
|
159
|
-
description="If true,
|
159
|
+
description="If true, a heuristic is used to determine if a function should be synthesized separately",
|
160
160
|
)
|
161
161
|
output_format: PydanticConstrainedQuantumFormatList = pydantic.Field(
|
162
162
|
default=[QuantumFormat.QASM],
|
@@ -26,26 +26,6 @@ class ControlledGate(_StandardGate): # type: ignore[misc]
|
|
26
26
|
num_ctrl_qubits: pydantic.PositiveInt = pydantic.Field(
|
27
27
|
default=DEFAULT_NUM_CTRL_QUBITS
|
28
28
|
)
|
29
|
-
|
30
|
-
def _create_ios(self) -> None:
|
31
|
-
_StandardGate._create_ios(self)
|
32
|
-
control = RegisterUserInput(
|
33
|
-
name=CONTROLLED_GATE_CONTROL, size=self.num_ctrl_qubits
|
34
|
-
)
|
35
|
-
self._inputs[CONTROLLED_GATE_CONTROL] = control
|
36
|
-
self._outputs[CONTROLLED_GATE_CONTROL] = control
|
37
|
-
|
38
|
-
def to_control_state(self) -> ControlState:
|
39
|
-
return ControlState(
|
40
|
-
name=CONTROLLED_GATE_CONTROL, num_ctrl_qubits=self.num_ctrl_qubits
|
41
|
-
)
|
42
|
-
|
43
|
-
|
44
|
-
class ControlledGateWithState(ControlledGate): # type: ignore[misc]
|
45
|
-
"""
|
46
|
-
Base model for controlled Gates with control over the controlled_state
|
47
|
-
"""
|
48
|
-
|
49
29
|
ctrl_state: CtrlState = pydantic.Field(
|
50
30
|
description="The control state in decimal or as a bit string (e.g. '1011'). If not specified, the control "
|
51
31
|
"state is 2**num_ctrl_qubits - 1.\n"
|
@@ -82,12 +62,20 @@ class ControlledGateWithState(ControlledGate): # type: ignore[misc]
|
|
82
62
|
)
|
83
63
|
return ControlState(name=CONTROLLED_GATE_CONTROL, ctrl_state=ctrl_state_str)
|
84
64
|
|
65
|
+
def _create_ios(self) -> None:
|
66
|
+
_StandardGate._create_ios(self)
|
67
|
+
control = RegisterUserInput(
|
68
|
+
name=CONTROLLED_GATE_CONTROL, size=self.num_ctrl_qubits
|
69
|
+
)
|
70
|
+
self._inputs[CONTROLLED_GATE_CONTROL] = control
|
71
|
+
self._outputs[CONTROLLED_GATE_CONTROL] = control
|
72
|
+
|
85
73
|
|
86
74
|
def _num_to_control_string(ctrl_state_int: int, num_ctrl_qubits: int) -> str:
|
87
75
|
return format(ctrl_state_int, f"0{num_ctrl_qubits}b")
|
88
76
|
|
89
77
|
|
90
|
-
class CXGate(
|
78
|
+
class CXGate(ControlledGate): # type: ignore[misc]
|
91
79
|
"""
|
92
80
|
The Controlled-X Gate
|
93
81
|
"""
|
@@ -98,7 +86,7 @@ class CXGate(ControlledGateWithState): # type: ignore[misc]
|
|
98
86
|
return 2
|
99
87
|
|
100
88
|
|
101
|
-
class CCXGate(
|
89
|
+
class CCXGate(ControlledGate): # type: ignore[misc]
|
102
90
|
"""
|
103
91
|
The Double Controlled-X Gate
|
104
92
|
"""
|
@@ -109,7 +97,7 @@ class CCXGate(ControlledGateWithState): # type: ignore[misc]
|
|
109
97
|
return 2
|
110
98
|
|
111
99
|
|
112
|
-
class C3XGate(
|
100
|
+
class C3XGate(ControlledGate): # type: ignore[misc]
|
113
101
|
"""
|
114
102
|
The X Gate controlled on 3 qubits
|
115
103
|
"""
|
@@ -121,7 +109,7 @@ class C3XGate(ControlledGateWithState): # type: ignore[misc]
|
|
121
109
|
return 2
|
122
110
|
|
123
111
|
|
124
|
-
class C4XGate(
|
112
|
+
class C4XGate(ControlledGate): # type: ignore[misc]
|
125
113
|
"""
|
126
114
|
The X Gate controlled on 4 qubits
|
127
115
|
"""
|
@@ -133,7 +121,7 @@ class C4XGate(ControlledGateWithState): # type: ignore[misc]
|
|
133
121
|
return 2
|
134
122
|
|
135
123
|
|
136
|
-
class CYGate(
|
124
|
+
class CYGate(ControlledGate): # type: ignore[misc]
|
137
125
|
"""
|
138
126
|
The Controlled-Y Gate
|
139
127
|
"""
|
@@ -142,7 +130,7 @@ class CYGate(ControlledGateWithState): # type: ignore[misc]
|
|
142
130
|
return 2
|
143
131
|
|
144
132
|
|
145
|
-
class CZGate(
|
133
|
+
class CZGate(ControlledGate): # type: ignore[misc]
|
146
134
|
"""
|
147
135
|
The Controlled-Z Gate
|
148
136
|
"""
|
@@ -151,7 +139,7 @@ class CZGate(ControlledGateWithState): # type: ignore[misc]
|
|
151
139
|
return 2
|
152
140
|
|
153
141
|
|
154
|
-
class CHGate(
|
142
|
+
class CHGate(ControlledGate): # type: ignore[misc]
|
155
143
|
"""
|
156
144
|
The Controlled-H Gate
|
157
145
|
"""
|
@@ -160,7 +148,7 @@ class CHGate(ControlledGateWithState): # type: ignore[misc]
|
|
160
148
|
return 2
|
161
149
|
|
162
150
|
|
163
|
-
class CSXGate(
|
151
|
+
class CSXGate(ControlledGate): # type: ignore[misc]
|
164
152
|
"""
|
165
153
|
The Controlled-SX Gate
|
166
154
|
"""
|
@@ -169,25 +157,25 @@ class CSXGate(ControlledGateWithState): # type: ignore[misc]
|
|
169
157
|
return 4
|
170
158
|
|
171
159
|
|
172
|
-
class CRXGate(
|
160
|
+
class CRXGate(ControlledGate, angles=["theta"]): # type: ignore[misc]
|
173
161
|
"""
|
174
162
|
The Controlled-RX Gate
|
175
163
|
"""
|
176
164
|
|
177
165
|
|
178
|
-
class CRYGate(
|
166
|
+
class CRYGate(ControlledGate, angles=["theta"]): # type: ignore[misc]
|
179
167
|
"""
|
180
168
|
The Controlled-RY Gate
|
181
169
|
"""
|
182
170
|
|
183
171
|
|
184
|
-
class CRZGate(
|
172
|
+
class CRZGate(ControlledGate, angles=["theta"]): # type: ignore[misc]
|
185
173
|
"""
|
186
174
|
The Controlled-RZ Gate
|
187
175
|
"""
|
188
176
|
|
189
177
|
|
190
|
-
class CPhaseGate(
|
178
|
+
class CPhaseGate(ControlledGate, angles=["theta"]): # type: ignore[misc]
|
191
179
|
"""
|
192
180
|
The Controlled-Phase Gate
|
193
181
|
"""
|
@@ -1 +1 @@
|
|
1
|
-
INTERFACE_VERSION = "
|
1
|
+
INTERFACE_VERSION = "6"
|
classiq/interface/model/model.py
CHANGED
@@ -180,9 +180,8 @@ class Model(VersionedModel, ASTNode):
|
|
180
180
|
)
|
181
181
|
return constants
|
182
182
|
|
183
|
-
def
|
184
|
-
return self.
|
185
|
-
indent=2,
|
183
|
+
def dump_no_preferences_and_constraints(self) -> dict[str, Any]:
|
184
|
+
return self.model_dump(
|
186
185
|
exclude={
|
187
186
|
"constraints",
|
188
187
|
"execution_preferences",
|
@@ -7,7 +7,6 @@ from typing import (
|
|
7
7
|
|
8
8
|
import pydantic
|
9
9
|
|
10
|
-
from classiq.interface.ast_node import ASTNode
|
11
10
|
from classiq.interface.exceptions import ClassiqError, ClassiqValueError
|
12
11
|
from classiq.interface.generator.expressions.expression import Expression
|
13
12
|
from classiq.interface.generator.functions.port_declaration import (
|
@@ -21,7 +20,10 @@ from classiq.interface.model.port_declaration import AnonPortDeclaration
|
|
21
20
|
from classiq.interface.model.quantum_function_declaration import (
|
22
21
|
QuantumFunctionDeclaration,
|
23
22
|
)
|
24
|
-
from classiq.interface.model.quantum_lambda_function import
|
23
|
+
from classiq.interface.model.quantum_lambda_function import (
|
24
|
+
OperandIdentifier,
|
25
|
+
QuantumOperand,
|
26
|
+
)
|
25
27
|
from classiq.interface.model.quantum_statement import HandleMetadata, QuantumOperation
|
26
28
|
|
27
29
|
ArgValue = Union[
|
@@ -31,11 +33,6 @@ ArgValue = Union[
|
|
31
33
|
]
|
32
34
|
|
33
35
|
|
34
|
-
class OperandIdentifier(ASTNode):
|
35
|
-
name: str
|
36
|
-
index: Expression
|
37
|
-
|
38
|
-
|
39
36
|
class QuantumFunctionCall(QuantumOperation):
|
40
37
|
kind: Literal["QuantumFunctionCall"]
|
41
38
|
|