classiq 0.70.0__py3-none-any.whl → 0.72.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 +0 -6
- classiq/_internals/client.py +11 -1
- classiq/applications/chemistry/chemistry_model_constructor.py +18 -16
- classiq/applications/combinatorial_helpers/optimization_model.py +9 -2
- classiq/applications/combinatorial_helpers/pyomo_utils.py +6 -1
- classiq/applications/finance/__init__.py +0 -3
- classiq/applications/qsvm/__init__.py +0 -2
- classiq/interface/_version.py +1 -1
- classiq/interface/backend/backend_preferences.py +22 -0
- classiq/interface/backend/quantum_backend_providers.py +2 -0
- classiq/interface/debug_info/debug_info.py +4 -0
- classiq/interface/generator/expressions/expression_constants.py +0 -3
- classiq/interface/generator/expressions/expression_types.py +8 -3
- classiq/interface/generator/expressions/proxies/classical/any_classical_value.py +135 -0
- classiq/interface/generator/expressions/proxies/classical/classical_array_proxy.py +4 -0
- classiq/interface/generator/expressions/proxies/classical/classical_struct_proxy.py +5 -1
- classiq/interface/generator/expressions/proxies/classical/utils.py +34 -0
- classiq/interface/generator/functions/builtins/internal_operators.py +1 -0
- classiq/interface/generator/functions/classical_type.py +1 -1
- classiq/interface/generator/functions/type_name.py +16 -0
- classiq/interface/generator/functions/type_qualifier.py +7 -0
- classiq/interface/generator/generated_circuit_data.py +14 -1
- classiq/interface/generator/hardware/hardware_data.py +3 -1
- classiq/interface/generator/quantum_function_call.py +8 -1
- classiq/interface/generator/synthesis_execution_parameter.py +1 -0
- classiq/interface/generator/transpiler_basis_gates.py +3 -1
- classiq/interface/generator/types/compilation_metadata.py +1 -0
- classiq/interface/hardware.py +1 -0
- classiq/interface/ide/visual_model.py +1 -0
- classiq/interface/interface_version.py +1 -1
- classiq/interface/model/allocate.py +7 -0
- classiq/interface/model/block.py +12 -0
- classiq/interface/model/classical_if.py +4 -0
- classiq/interface/model/handle_binding.py +21 -0
- classiq/interface/model/inplace_binary_operation.py +4 -0
- classiq/interface/model/model.py +3 -1
- classiq/interface/model/phase_operation.py +4 -0
- classiq/interface/model/port_declaration.py +3 -0
- classiq/interface/model/power.py +4 -0
- classiq/interface/model/quantum_expressions/quantum_expression.py +4 -0
- classiq/interface/model/quantum_function_call.py +4 -0
- classiq/interface/model/quantum_function_declaration.py +1 -1
- classiq/interface/model/quantum_statement.py +5 -0
- classiq/interface/model/quantum_type.py +22 -0
- classiq/interface/model/repeat.py +4 -0
- classiq/interface/model/statement_block.py +3 -0
- classiq/interface/model/variable_declaration_statement.py +5 -0
- classiq/interface/server/routes.py +0 -2
- classiq/model_expansions/atomic_expression_functions_defs.py +35 -13
- classiq/model_expansions/capturing/captured_vars.py +156 -34
- classiq/model_expansions/closure.py +0 -9
- classiq/model_expansions/evaluators/classical_type_inference.py +70 -0
- classiq/model_expansions/evaluators/parameter_types.py +20 -10
- classiq/model_expansions/expression_evaluator.py +0 -11
- classiq/model_expansions/function_builder.py +2 -8
- classiq/model_expansions/generative_functions.py +7 -30
- classiq/model_expansions/interpreters/base_interpreter.py +7 -8
- classiq/model_expansions/interpreters/generative_interpreter.py +33 -5
- classiq/model_expansions/quantum_operations/__init__.py +0 -2
- classiq/model_expansions/quantum_operations/block_evaluator.py +16 -2
- classiq/model_expansions/quantum_operations/call_emitter.py +49 -6
- classiq/model_expansions/quantum_operations/emitter.py +64 -6
- classiq/model_expansions/quantum_operations/expression_evaluator.py +4 -0
- classiq/model_expansions/quantum_operations/handle_evaluator.py +1 -1
- classiq/model_expansions/quantum_operations/quantum_function_call.py +49 -0
- classiq/model_expansions/quantum_operations/repeat_block_evaluator.py +34 -0
- classiq/model_expansions/scope.py +33 -21
- classiq/model_expansions/scope_initialization.py +28 -32
- classiq/model_expansions/transformers/model_renamer.py +69 -63
- classiq/model_expansions/utils/sympy_utils.py +24 -0
- classiq/model_expansions/visitors/variable_references.py +1 -0
- classiq/qmod/__init__.py +3 -1
- classiq/qmod/builtins/functions/__init__.py +8 -0
- classiq/qmod/builtins/functions/allocation.py +36 -0
- classiq/qmod/builtins/functions/arithmetic.py +10 -5
- classiq/qmod/builtins/functions/mid_circuit_measurement.py +3 -0
- classiq/qmod/builtins/operations.py +2 -2
- classiq/qmod/declaration_inferrer.py +52 -24
- classiq/qmod/model_state_container.py +9 -0
- classiq/qmod/native/pretty_printer.py +25 -3
- classiq/qmod/pretty_print/pretty_printer.py +31 -14
- classiq/qmod/python_classical_type.py +12 -1
- classiq/qmod/qfunc.py +33 -8
- classiq/qmod/qmod_variable.py +188 -147
- classiq/qmod/quantum_function.py +3 -4
- classiq/qmod/semantics/validation/type_hints.py +19 -10
- classiq/qmod/symbolic.py +16 -3
- {classiq-0.70.0.dist-info → classiq-0.72.0.dist-info}/METADATA +1 -1
- {classiq-0.70.0.dist-info → classiq-0.72.0.dist-info}/RECORD +90 -91
- classiq/applications/finance/finance_model_constructor.py +0 -137
- classiq/applications/grover/__init__.py +0 -9
- classiq/applications/grover/grover_model_constructor.py +0 -167
- classiq/applications/libraries/__init__.py +0 -0
- classiq/applications/libraries/qmci_library.py +0 -22
- classiq/applications/qsvm/qsvm_model_constructor.py +0 -131
- classiq/model_expansions/quantum_operations/classicalif.py +0 -57
- classiq/model_expansions/quantum_operations/repeat.py +0 -62
- {classiq-0.70.0.dist-info → classiq-0.72.0.dist-info}/WHEEL +0 -0
classiq/__init__.py
CHANGED
@@ -34,13 +34,10 @@ from classiq.applications.combinatorial_optimization import (
|
|
34
34
|
execute_qaoa,
|
35
35
|
pyo_model_to_hamiltonian,
|
36
36
|
)
|
37
|
-
from classiq.applications.finance import construct_finance_model
|
38
|
-
from classiq.applications.grover import construct_grover_model
|
39
37
|
from classiq.applications.hamiltonian.pauli_decomposition import (
|
40
38
|
hamiltonian_to_matrix,
|
41
39
|
matrix_to_hamiltonian,
|
42
40
|
)
|
43
|
-
from classiq.applications.qsvm import construct_qsvm_model
|
44
41
|
from classiq.executor import (
|
45
42
|
execute,
|
46
43
|
execute_async,
|
@@ -65,11 +62,8 @@ from classiq.synthesis import (
|
|
65
62
|
)
|
66
63
|
|
67
64
|
_application_constructors_all = [
|
68
|
-
"construct_qsvm_model",
|
69
65
|
"construct_combinatorial_optimization_model",
|
70
66
|
"construct_chemistry_model",
|
71
|
-
"construct_finance_model",
|
72
|
-
"construct_grover_model",
|
73
67
|
"molecule_problem_to_qmod",
|
74
68
|
]
|
75
69
|
|
classiq/_internals/client.py
CHANGED
@@ -23,6 +23,7 @@ from classiq._internals.authentication import token_manager
|
|
23
23
|
from classiq._internals.host_checker import HostChecker
|
24
24
|
|
25
25
|
_FRONTEND_VARIANT: str = "classiq-sdk"
|
26
|
+
_SDK_ENV: str = "sdk-env"
|
26
27
|
_INTERFACE_VARIANT: str = "classiq-interface-sdk"
|
27
28
|
_USERAGENT_SEPARATOR: str = " "
|
28
29
|
|
@@ -74,12 +75,21 @@ def _get_user_agent_header() -> Headers:
|
|
74
75
|
python_version = (
|
75
76
|
f"python({_get_python_execution_environment()})/{platform.python_version()}"
|
76
77
|
)
|
78
|
+
|
79
|
+
sdk_env_value = os.getenv("SDK_ENV", "Default")
|
77
80
|
os_platform = f"{os.name}/{platform.platform()}"
|
78
81
|
frontend_version = f"{_FRONTEND_VARIANT}/{_VERSION}"
|
79
82
|
interface_version = f"{_INTERFACE_VARIANT}/{_VERSION}"
|
83
|
+
sdk_env = f"{_SDK_ENV}/{sdk_env_value}"
|
80
84
|
return {
|
81
85
|
"User-Agent": _USERAGENT_SEPARATOR.join(
|
82
|
-
(
|
86
|
+
(
|
87
|
+
python_version,
|
88
|
+
os_platform,
|
89
|
+
frontend_version,
|
90
|
+
interface_version,
|
91
|
+
sdk_env,
|
92
|
+
)
|
83
93
|
)
|
84
94
|
}
|
85
95
|
|
@@ -1,30 +1,17 @@
|
|
1
|
-
# flake8: noqa
|
2
|
-
|
3
|
-
from typing import Optional, cast
|
4
1
|
from collections.abc import Mapping
|
2
|
+
from typing import Optional, cast
|
5
3
|
|
6
4
|
from classiq.interface.chemistry.fermionic_operator import (
|
7
5
|
FermionicOperator,
|
8
6
|
SummedFermionicOperator,
|
9
7
|
)
|
10
|
-
from classiq.interface.model.allocate import Allocate
|
11
|
-
from classiq.interface.model.quantum_statement import QuantumStatement
|
12
|
-
from classiq.qmod.builtins.structs import (
|
13
|
-
MoleculeProblem as QmodMoleculeProblem,
|
14
|
-
Molecule as QmodMolecule,
|
15
|
-
ChemistryAtom as QmodChemistryAtom,
|
16
|
-
Position as QmodPosition,
|
17
|
-
)
|
18
8
|
from classiq.interface.chemistry.ground_state_problem import (
|
19
9
|
CHEMISTRY_PROBLEMS_TYPE,
|
20
10
|
HamiltonianProblem,
|
21
11
|
MoleculeProblem,
|
22
12
|
)
|
23
13
|
from classiq.interface.chemistry.molecule import Atom
|
24
|
-
from classiq.
|
25
|
-
Element,
|
26
|
-
FermionMapping,
|
27
|
-
)
|
14
|
+
from classiq.interface.exceptions import ClassiqError
|
28
15
|
from classiq.interface.generator.expressions.expression import Expression
|
29
16
|
from classiq.interface.generator.function_params import IOName
|
30
17
|
from classiq.interface.generator.functions.classical_type import (
|
@@ -34,6 +21,7 @@ from classiq.interface.generator.functions.classical_type import (
|
|
34
21
|
from classiq.interface.generator.functions.port_declaration import (
|
35
22
|
PortDeclarationDirection,
|
36
23
|
)
|
24
|
+
from classiq.interface.model.allocate import Allocate
|
37
25
|
from classiq.interface.model.classical_parameter_declaration import (
|
38
26
|
ClassicalParameterDeclaration,
|
39
27
|
)
|
@@ -43,6 +31,7 @@ from classiq.interface.model.native_function_definition import NativeFunctionDef
|
|
43
31
|
from classiq.interface.model.port_declaration import PortDeclaration
|
44
32
|
from classiq.interface.model.quantum_function_call import QuantumFunctionCall
|
45
33
|
from classiq.interface.model.quantum_lambda_function import QuantumLambdaFunction
|
34
|
+
from classiq.interface.model.quantum_statement import QuantumStatement
|
46
35
|
|
47
36
|
from classiq.applications.chemistry.ansatz_parameters import (
|
48
37
|
AnsatzParameters,
|
@@ -53,8 +42,21 @@ from classiq.applications.chemistry.ansatz_parameters import (
|
|
53
42
|
from classiq.applications.chemistry.chemistry_execution_parameters import (
|
54
43
|
ChemistryExecutionParameters,
|
55
44
|
)
|
56
|
-
from classiq.
|
45
|
+
from classiq.qmod.builtins.enums import (
|
46
|
+
Element,
|
47
|
+
FermionMapping,
|
48
|
+
)
|
49
|
+
from classiq.qmod.builtins.structs import (
|
50
|
+
ChemistryAtom as QmodChemistryAtom,
|
51
|
+
Molecule as QmodMolecule,
|
52
|
+
MoleculeProblem as QmodMoleculeProblem,
|
53
|
+
Position as QmodPosition,
|
54
|
+
)
|
57
55
|
from classiq.qmod.utilities import qmod_val_to_expr_str
|
56
|
+
|
57
|
+
# isort: split
|
58
|
+
|
59
|
+
# This import causes a circular import if done earlier. We use isort: split to avoid it
|
58
60
|
from classiq.open_library.functions.hea import full_hea
|
59
61
|
|
60
62
|
_LADDER_OPERATOR_TYPE_INDICATOR_TO_QMOD_MAPPING: dict[str, str] = {
|
@@ -4,6 +4,7 @@ from itertools import filterfalse
|
|
4
4
|
from typing import Optional, Union
|
5
5
|
|
6
6
|
import pyomo.environ as pyo
|
7
|
+
import sympy
|
7
8
|
from pyomo.core import ConcreteModel
|
8
9
|
from pyomo.core.base import _GeneralVarData
|
9
10
|
from pyomo.core.base.constraint import _GeneralConstraintData
|
@@ -179,8 +180,13 @@ class OptimizationModel:
|
|
179
180
|
objective_map.sympy2pyomo |= penalty_map.sympy2pyomo
|
180
181
|
for key, value in penalty_map.pyomo2sympy.items():
|
181
182
|
objective_map.pyomo2sympy[key] = value
|
183
|
+
sympy_renaming = {
|
184
|
+
var: sympy.Symbol(str(var).replace(",", "_").replace("'", "_"))
|
185
|
+
for var in objective_expr.free_symbols
|
186
|
+
}
|
187
|
+
objective_expr = objective_expr.subs(sympy_renaming)
|
182
188
|
sympy_mapping = {
|
183
|
-
sympy_var: (
|
189
|
+
sympy_renaming[sympy_var]: (
|
184
190
|
get_field_name(pyomo_var)
|
185
191
|
if not is_index_var(pyomo_var)
|
186
192
|
else (
|
@@ -190,4 +196,5 @@ class OptimizationModel:
|
|
190
196
|
)
|
191
197
|
for pyomo_var, sympy_var in objective_map.pyomo2sympy.items()
|
192
198
|
}
|
193
|
-
|
199
|
+
compiled_expr = compile(str(objective_expr), "<string>", "eval")
|
200
|
+
self.objective_not_encoded_sympy = sympy_mapping, objective_expr, compiled_expr
|
@@ -7,6 +7,7 @@ from contextlib import contextmanager
|
|
7
7
|
from enum import Enum
|
8
8
|
from functools import reduce
|
9
9
|
from operator import mul
|
10
|
+
from types import CodeType
|
10
11
|
from typing import Any, Optional, TypeVar, Union
|
11
12
|
|
12
13
|
import pydantic
|
@@ -362,6 +363,7 @@ def _get_qmod_field_type(var_name: str, var_data: _GeneralVarData) -> type[QVar]
|
|
362
363
|
def evaluate_objective(
|
363
364
|
var_mapping: dict[Any, Union[str, tuple[str, tuple[int, ...]]]],
|
364
365
|
sympy_expr: sympy.Expr,
|
366
|
+
code_expr: CodeType,
|
365
367
|
struct_obj: Any,
|
366
368
|
) -> Any:
|
367
369
|
sympy_assignment = {
|
@@ -375,7 +377,10 @@ def evaluate_objective(
|
|
375
377
|
|
376
378
|
# classical objective evaluation
|
377
379
|
if not isinstance(struct_obj, QStruct):
|
378
|
-
|
380
|
+
var_assignment = {
|
381
|
+
str(sympy_var): value for sympy_var, value in sympy_assignment.items()
|
382
|
+
}
|
383
|
+
return eval(code_expr, {}, var_assignment) # noqa: S307
|
379
384
|
|
380
385
|
# quantum objective evaluation
|
381
386
|
expr_str = str(sympy_expr).replace("'", "")
|
@@ -2,9 +2,7 @@ from classiq.qmod.builtins.enums import QSVMFeatureMapEntanglement
|
|
2
2
|
|
3
3
|
from ..qsvm import qsvm_data_generation
|
4
4
|
from .qsvm import * # noqa: F403
|
5
|
-
from .qsvm_model_constructor import construct_qsvm_model
|
6
5
|
|
7
6
|
__all__ = [
|
8
7
|
"QSVMFeatureMapEntanglement",
|
9
|
-
"construct_qsvm_model",
|
10
8
|
]
|
classiq/interface/_version.py
CHANGED
@@ -477,6 +477,27 @@ class IQCCBackendPreferences(BackendPreferences):
|
|
477
477
|
slurm_account: str
|
478
478
|
|
479
479
|
|
480
|
+
class CINECABackendPreferences(BackendPreferences):
|
481
|
+
"""
|
482
|
+
Represents the backend preferences specific to CINECA.
|
483
|
+
|
484
|
+
Attributes:
|
485
|
+
ssh_username: The username to use when connecting to the SSH server on the login node.
|
486
|
+
ssh_private_key_path: The path to the ssh private key on local machine.
|
487
|
+
"""
|
488
|
+
|
489
|
+
backend_service_provider: ProviderTypeVendor.CINECA = pydantic.Field(
|
490
|
+
default=ProviderVendor.CINECA
|
491
|
+
)
|
492
|
+
|
493
|
+
ssh_username: str = pydantic.Field(
|
494
|
+
description="Username to use when connecting to the SSH server on the login node."
|
495
|
+
)
|
496
|
+
ssh_private_key_path: str = pydantic.Field(
|
497
|
+
description="Path of private key file on local machine to use when connecting to the SSH server on the login node."
|
498
|
+
)
|
499
|
+
|
500
|
+
|
480
501
|
def is_exact_simulator(backend_preferences: BackendPreferences) -> bool:
|
481
502
|
return backend_preferences.backend_name in EXACT_SIMULATORS
|
482
503
|
|
@@ -509,6 +530,7 @@ BackendPreferencesTypes = Union[
|
|
509
530
|
IntelBackendPreferences,
|
510
531
|
AQTBackendPreferences,
|
511
532
|
IQCCBackendPreferences,
|
533
|
+
CINECABackendPreferences,
|
512
534
|
]
|
513
535
|
|
514
536
|
__all__ = [
|
@@ -21,6 +21,7 @@ class ProviderVendor(StrEnum):
|
|
21
21
|
INTEL = "Intel"
|
22
22
|
AQT = "AQT"
|
23
23
|
IQCC = "IQCC"
|
24
|
+
CINECA = "CINECA"
|
24
25
|
|
25
26
|
|
26
27
|
class ProviderTypeVendor:
|
@@ -35,6 +36,7 @@ class ProviderTypeVendor:
|
|
35
36
|
INTEL = Literal[ProviderVendor.INTEL]
|
36
37
|
AQT = Literal[ProviderVendor.AQT]
|
37
38
|
IQCC = Literal[ProviderVendor.IQCC]
|
39
|
+
CINECA = Literal[ProviderVendor.CINECA]
|
38
40
|
|
39
41
|
|
40
42
|
class ClassiqSimulatorBackendNames(StrEnum):
|
@@ -10,6 +10,7 @@ from classiq.interface.generator.generated_circuit_data import (
|
|
10
10
|
OperationLevel,
|
11
11
|
StatementType,
|
12
12
|
)
|
13
|
+
from classiq.interface.model.block import Block
|
13
14
|
from classiq.interface.model.statement_block import ConcreteQuantumStatement
|
14
15
|
|
15
16
|
ParameterValue = Union[float, int, str, None]
|
@@ -84,6 +85,9 @@ def get_back_refs(
|
|
84
85
|
) -> list[ConcreteQuantumStatement]:
|
85
86
|
back_refs: list[ConcreteQuantumStatement] = []
|
86
87
|
while (node := debug_info.node) is not None:
|
88
|
+
# For backwards compatibility, we make sure that the back_ref is not a block
|
89
|
+
# Remove this check when we start saving blocks in the debug info collection.
|
90
|
+
assert not isinstance(node, Block)
|
87
91
|
back_refs.insert(0, node)
|
88
92
|
if node.back_ref is None:
|
89
93
|
break
|
@@ -20,6 +20,3 @@ 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
|
-
)
|
@@ -4,6 +4,9 @@ from sympy import Expr
|
|
4
4
|
from sympy.logic.boolalg import Boolean
|
5
5
|
|
6
6
|
from classiq.interface.generator.expressions.handle_identifier import HandleIdentifier
|
7
|
+
from classiq.interface.generator.expressions.proxies.classical.any_classical_value import (
|
8
|
+
AnyClassicalValue,
|
9
|
+
)
|
7
10
|
from classiq.interface.generator.expressions.proxies.classical.classical_proxy import (
|
8
11
|
ClassicalProxy,
|
9
12
|
)
|
@@ -21,10 +24,12 @@ RuntimeConstant = Union[
|
|
21
24
|
list,
|
22
25
|
bool,
|
23
26
|
QmodStructInstance,
|
24
|
-
QmodSizedProxy,
|
25
27
|
TypeProxy,
|
26
28
|
HandleIdentifier,
|
29
|
+
]
|
30
|
+
Proxies = Union[
|
31
|
+
QmodSizedProxy,
|
27
32
|
ClassicalProxy,
|
28
33
|
]
|
29
|
-
RuntimeExpression = Union[Expr, Boolean]
|
30
|
-
ExpressionValue = Union[RuntimeConstant, RuntimeExpression]
|
34
|
+
RuntimeExpression = Union[AnyClassicalValue, Expr, Boolean]
|
35
|
+
ExpressionValue = Union[RuntimeConstant, Proxies, RuntimeExpression]
|
@@ -0,0 +1,135 @@
|
|
1
|
+
from typing import Any
|
2
|
+
|
3
|
+
|
4
|
+
class AnyClassicalValue:
|
5
|
+
def __init__(self, expr: str) -> None:
|
6
|
+
self._expr = expr
|
7
|
+
|
8
|
+
def __str__(self) -> str:
|
9
|
+
return self._expr
|
10
|
+
|
11
|
+
def __repr__(self) -> str:
|
12
|
+
return str(self)
|
13
|
+
|
14
|
+
def __getitem__(self, item: Any) -> "AnyClassicalValue":
|
15
|
+
if isinstance(item, slice):
|
16
|
+
subscript = ""
|
17
|
+
if item.start is not None:
|
18
|
+
subscript += str(item.start)
|
19
|
+
subscript += ":"
|
20
|
+
if item.stop is not None:
|
21
|
+
subscript += str(item.stop)
|
22
|
+
if item.step is not None:
|
23
|
+
subscript += f":{item.stop}"
|
24
|
+
item = subscript
|
25
|
+
return AnyClassicalValue(f"{self}[{item}]")
|
26
|
+
|
27
|
+
@staticmethod
|
28
|
+
def _binary_op(lhs: Any, rhs: Any, op: str) -> "AnyClassicalValue":
|
29
|
+
return AnyClassicalValue(f"{lhs} {op} {rhs}")
|
30
|
+
|
31
|
+
@staticmethod
|
32
|
+
def _unary_op(arg: Any, op: str) -> "AnyClassicalValue":
|
33
|
+
return AnyClassicalValue(f"{op}({arg})")
|
34
|
+
|
35
|
+
def __add__(self, other: Any) -> "AnyClassicalValue":
|
36
|
+
return AnyClassicalValue._binary_op(self, other, "+")
|
37
|
+
|
38
|
+
def __sub__(self, other: Any) -> "AnyClassicalValue":
|
39
|
+
return AnyClassicalValue._binary_op(self, other, "-")
|
40
|
+
|
41
|
+
def __mul__(self, other: Any) -> "AnyClassicalValue":
|
42
|
+
return AnyClassicalValue._binary_op(self, other, "*")
|
43
|
+
|
44
|
+
def __truediv__(self, other: Any) -> "AnyClassicalValue":
|
45
|
+
return AnyClassicalValue._binary_op(self, other, "/")
|
46
|
+
|
47
|
+
def __floordiv__(self, other: Any) -> "AnyClassicalValue":
|
48
|
+
return AnyClassicalValue._binary_op(self, other, "//")
|
49
|
+
|
50
|
+
def __mod__(self, other: Any) -> "AnyClassicalValue":
|
51
|
+
return AnyClassicalValue._binary_op(self, other, "%")
|
52
|
+
|
53
|
+
def __pow__(self, other: Any) -> "AnyClassicalValue":
|
54
|
+
return AnyClassicalValue._binary_op(self, other, "**")
|
55
|
+
|
56
|
+
def __lshift__(self, other: Any) -> "AnyClassicalValue":
|
57
|
+
return AnyClassicalValue._binary_op(self, other, "<<")
|
58
|
+
|
59
|
+
def __rshift__(self, other: Any) -> "AnyClassicalValue":
|
60
|
+
return AnyClassicalValue._binary_op(self, other, ">>")
|
61
|
+
|
62
|
+
def __and__(self, other: Any) -> "AnyClassicalValue":
|
63
|
+
return AnyClassicalValue._binary_op(self, other, "&")
|
64
|
+
|
65
|
+
def __xor__(self, other: Any) -> "AnyClassicalValue":
|
66
|
+
return AnyClassicalValue._binary_op(self, other, "^")
|
67
|
+
|
68
|
+
def __or__(self, other: Any) -> "AnyClassicalValue":
|
69
|
+
return AnyClassicalValue._binary_op(self, other, "|")
|
70
|
+
|
71
|
+
def __radd__(self, other: Any) -> "AnyClassicalValue":
|
72
|
+
return AnyClassicalValue._binary_op(other, self, "+")
|
73
|
+
|
74
|
+
def __rsub__(self, other: Any) -> "AnyClassicalValue":
|
75
|
+
return AnyClassicalValue._binary_op(other, self, "-")
|
76
|
+
|
77
|
+
def __rmul__(self, other: Any) -> "AnyClassicalValue":
|
78
|
+
return AnyClassicalValue._binary_op(other, self, "*")
|
79
|
+
|
80
|
+
def __rtruediv__(self, other: Any) -> "AnyClassicalValue":
|
81
|
+
return AnyClassicalValue._binary_op(other, self, "/")
|
82
|
+
|
83
|
+
def __rfloordiv__(self, other: Any) -> "AnyClassicalValue":
|
84
|
+
return AnyClassicalValue._binary_op(other, self, "//")
|
85
|
+
|
86
|
+
def __rmod__(self, other: Any) -> "AnyClassicalValue":
|
87
|
+
return AnyClassicalValue._binary_op(other, self, "%")
|
88
|
+
|
89
|
+
def __rpow__(self, other: Any) -> "AnyClassicalValue":
|
90
|
+
return AnyClassicalValue._binary_op(other, self, "**")
|
91
|
+
|
92
|
+
def __rlshift__(self, other: Any) -> "AnyClassicalValue":
|
93
|
+
return AnyClassicalValue._binary_op(other, self, "<<")
|
94
|
+
|
95
|
+
def __rrshift__(self, other: Any) -> "AnyClassicalValue":
|
96
|
+
return AnyClassicalValue._binary_op(other, self, ">>")
|
97
|
+
|
98
|
+
def __rand__(self, other: Any) -> "AnyClassicalValue":
|
99
|
+
return AnyClassicalValue._binary_op(other, self, "&")
|
100
|
+
|
101
|
+
def __rxor__(self, other: Any) -> "AnyClassicalValue":
|
102
|
+
return AnyClassicalValue._binary_op(other, self, "^")
|
103
|
+
|
104
|
+
def __ror__(self, other: Any) -> "AnyClassicalValue":
|
105
|
+
return AnyClassicalValue._binary_op(other, self, "|")
|
106
|
+
|
107
|
+
def __lt__(self, other: Any) -> "AnyClassicalValue":
|
108
|
+
return AnyClassicalValue._binary_op(self, other, "<")
|
109
|
+
|
110
|
+
def __le__(self, other: Any) -> "AnyClassicalValue":
|
111
|
+
return AnyClassicalValue._binary_op(self, other, "<=")
|
112
|
+
|
113
|
+
def __eq__(self, other: Any) -> "AnyClassicalValue": # type:ignore[override]
|
114
|
+
return AnyClassicalValue._binary_op(self, other, "==")
|
115
|
+
|
116
|
+
def __ne__(self, other: Any) -> "AnyClassicalValue": # type: ignore[override]
|
117
|
+
return AnyClassicalValue._binary_op(self, other, "!=")
|
118
|
+
|
119
|
+
def __gt__(self, other: Any) -> "AnyClassicalValue":
|
120
|
+
return AnyClassicalValue._binary_op(self, other, ">")
|
121
|
+
|
122
|
+
def __ge__(self, other: Any) -> "AnyClassicalValue":
|
123
|
+
return AnyClassicalValue._binary_op(self, other, ">=")
|
124
|
+
|
125
|
+
def __neg__(self) -> "AnyClassicalValue":
|
126
|
+
return AnyClassicalValue._unary_op(self, "-")
|
127
|
+
|
128
|
+
def __pos__(self) -> "AnyClassicalValue":
|
129
|
+
return AnyClassicalValue._unary_op(self, "+")
|
130
|
+
|
131
|
+
def __abs__(self) -> "AnyClassicalValue":
|
132
|
+
return AnyClassicalValue._unary_op(self, "abs")
|
133
|
+
|
134
|
+
def __invert__(self) -> "AnyClassicalValue":
|
135
|
+
return AnyClassicalValue._unary_op(self, "~")
|
@@ -38,6 +38,10 @@ class ClassicalArrayProxy(NonSymbolicExpr, ClassicalProxy):
|
|
38
38
|
def type_name(self) -> str:
|
39
39
|
return "Array"
|
40
40
|
|
41
|
+
@property
|
42
|
+
def length(self) -> int:
|
43
|
+
return self._length
|
44
|
+
|
41
45
|
def __getitem__(self, key: Union[slice, int, Integer]) -> ClassicalProxy:
|
42
46
|
return (
|
43
47
|
self._get_slice(key) if isinstance(key, slice) else self._get_subscript(key)
|
@@ -17,11 +17,15 @@ class ClassicalStructProxy(NonSymbolicExpr, ClassicalProxy):
|
|
17
17
|
super().__init__(handle)
|
18
18
|
self._decl = decl
|
19
19
|
|
20
|
+
@property
|
21
|
+
def struct_declaration(self) -> "StructDeclaration":
|
22
|
+
return self._decl
|
23
|
+
|
20
24
|
@property
|
21
25
|
def fields(self) -> Mapping[str, "ExpressionValue"]:
|
22
26
|
return {
|
23
27
|
field_name: field_type.get_classical_proxy(
|
24
|
-
FieldHandleBinding(base_handle=self.handle,
|
28
|
+
FieldHandleBinding(base_handle=self.handle, field=field_name)
|
25
29
|
)
|
26
30
|
for field_name, field_type in self._decl.variables.items()
|
27
31
|
}
|
@@ -0,0 +1,34 @@
|
|
1
|
+
from classiq.interface.exceptions import ClassiqInternalExpansionError
|
2
|
+
from classiq.interface.generator.expressions.proxies.classical.classical_array_proxy import (
|
3
|
+
ClassicalArrayProxy,
|
4
|
+
)
|
5
|
+
from classiq.interface.generator.expressions.proxies.classical.classical_proxy import (
|
6
|
+
ClassicalProxy,
|
7
|
+
)
|
8
|
+
from classiq.interface.generator.expressions.proxies.classical.classical_scalar_proxy import (
|
9
|
+
ClassicalScalarProxy,
|
10
|
+
)
|
11
|
+
from classiq.interface.generator.expressions.proxies.classical.classical_struct_proxy import (
|
12
|
+
ClassicalStructProxy,
|
13
|
+
)
|
14
|
+
from classiq.interface.generator.functions.classical_type import (
|
15
|
+
ClassicalArray,
|
16
|
+
ClassicalType,
|
17
|
+
)
|
18
|
+
from classiq.interface.generator.functions.type_name import TypeName
|
19
|
+
|
20
|
+
|
21
|
+
def get_proxy_type(proxy: ClassicalProxy) -> ClassicalType:
|
22
|
+
if isinstance(proxy, ClassicalScalarProxy):
|
23
|
+
classical_type = proxy._classical_type
|
24
|
+
elif isinstance(proxy, ClassicalArrayProxy):
|
25
|
+
classical_type = ClassicalArray(
|
26
|
+
element_type=proxy._element_type, size=proxy.length
|
27
|
+
)
|
28
|
+
elif isinstance(proxy, ClassicalStructProxy):
|
29
|
+
classical_type = TypeName(name=proxy._decl.name)
|
30
|
+
else:
|
31
|
+
raise ClassiqInternalExpansionError(
|
32
|
+
f"Unrecognized classical proxy {type(proxy).__name__}"
|
33
|
+
)
|
34
|
+
return classical_type
|
@@ -2,6 +2,7 @@ CTRL_VAR_PREFIX = "ctrl__"
|
|
2
2
|
CONTROL_OPERATOR_NAME = "control"
|
3
3
|
INVERT_OPERATOR_NAME = "invert"
|
4
4
|
REPEAT_OPERATOR_NAME = "iteration"
|
5
|
+
CLASSICAL_IF_OPERATOR_NAME = "classical_if"
|
5
6
|
POWER_OPERATOR_NAME = "power"
|
6
7
|
UNCOMPUTE_OPERATOR_NAME = "uncompute"
|
7
8
|
WITHIN_APPLY_NAME = "within_apply"
|
@@ -1,9 +1,11 @@
|
|
1
1
|
from collections.abc import Mapping
|
2
|
+
from itertools import chain
|
2
3
|
from typing import TYPE_CHECKING, Any, Literal, Optional
|
3
4
|
|
4
5
|
import pydantic
|
5
6
|
|
6
7
|
from classiq.interface.exceptions import ClassiqExpansionError
|
8
|
+
from classiq.interface.generator.expressions.expression import Expression
|
7
9
|
from classiq.interface.generator.expressions.proxies.classical.classical_proxy import (
|
8
10
|
ClassicalProxy,
|
9
11
|
)
|
@@ -97,6 +99,12 @@ class TypeName(ClassicalType, QuantumType):
|
|
97
99
|
def has_classical_struct_decl(self) -> bool:
|
98
100
|
return self._classical_struct_decl is not None
|
99
101
|
|
102
|
+
@property
|
103
|
+
def classical_struct_decl(self) -> "StructDeclaration":
|
104
|
+
if self._classical_struct_decl is None:
|
105
|
+
raise ClassiqExpansionError(f"Type {self.name!r} is undefined")
|
106
|
+
return self._classical_struct_decl
|
107
|
+
|
100
108
|
def set_classical_struct_decl(self, decl: "StructDeclaration") -> None:
|
101
109
|
self._classical_struct_decl = decl
|
102
110
|
|
@@ -105,6 +113,14 @@ class TypeName(ClassicalType, QuantumType):
|
|
105
113
|
raise ClassiqExpansionError(f"Type {self.name!r} is undefined")
|
106
114
|
return ClassicalStructProxy(handle, self._classical_struct_decl)
|
107
115
|
|
116
|
+
@property
|
117
|
+
def expressions(self) -> list[Expression]:
|
118
|
+
return list(
|
119
|
+
chain.from_iterable(
|
120
|
+
field_type.expressions for field_type in self.fields.values()
|
121
|
+
)
|
122
|
+
)
|
123
|
+
|
108
124
|
|
109
125
|
class Enum(TypeName):
|
110
126
|
pass
|
@@ -83,7 +83,7 @@ class GeneratedRegister(pydantic.BaseModel):
|
|
83
83
|
@staticmethod
|
84
84
|
def demangle_name(name: str) -> str:
|
85
85
|
if is_captured_var_name(name):
|
86
|
-
|
86
|
+
name = demangle_capture_name(name)
|
87
87
|
return demangle_name(name)
|
88
88
|
|
89
89
|
|
@@ -233,6 +233,19 @@ class FunctionDebugInfoInterface(pydantic.BaseModel):
|
|
233
233
|
return list()
|
234
234
|
return self.generated_function.control_states
|
235
235
|
|
236
|
+
@property
|
237
|
+
def control_qubits(self) -> tuple[int, ...]:
|
238
|
+
control_states_names = {
|
239
|
+
control_state.name for control_state in self.control_states
|
240
|
+
}
|
241
|
+
return tuple(
|
242
|
+
qubit
|
243
|
+
for register in self.registers
|
244
|
+
for qubit in register.qubit_indexes_absolute
|
245
|
+
if register.role is RegisterRole.INPUT
|
246
|
+
and register.name in control_states_names
|
247
|
+
)
|
248
|
+
|
236
249
|
def propagate_absolute_qubits(self) -> "FunctionDebugInfoInterface":
|
237
250
|
if self.absolute_qubits is None:
|
238
251
|
return self
|
@@ -110,10 +110,12 @@ class HardwareData(pydantic.BaseModel):
|
|
110
110
|
for gate in specified_basis_gates
|
111
111
|
if gate in TWO_QUBIT_GATES and gate not in ROUTING_TWO_QUBIT_BASIS_GATES
|
112
112
|
]
|
113
|
+
|
113
114
|
if invalid_gates:
|
114
115
|
raise ClassiqValueError(
|
115
116
|
"Connectivity-aware synthesis with non-symmetric coupling map "
|
116
|
-
"is currently supported for the following two-qubit gates only:
|
117
|
+
"is currently supported for the following two-qubit gates only: "
|
118
|
+
"cx, ecr, rzx, ryy, rxx, rzz, cy, cp, cz, swap"
|
117
119
|
)
|
118
120
|
|
119
121
|
return self
|
@@ -40,7 +40,10 @@ from classiq.interface.generator.slice_parsing_utils import (
|
|
40
40
|
SLICING,
|
41
41
|
parse_io_slicing,
|
42
42
|
)
|
43
|
-
from classiq.interface.generator.synthesis_execution_parameter import
|
43
|
+
from classiq.interface.generator.synthesis_execution_parameter import (
|
44
|
+
ClassicalArg,
|
45
|
+
PydanticPowerType,
|
46
|
+
)
|
44
47
|
from classiq.interface.generator.user_defined_function_params import CustomFunction
|
45
48
|
from classiq.interface.helpers.custom_pydantic_types import PydanticNonEmptyString
|
46
49
|
from classiq.interface.helpers.hashable_pydantic_base_model import (
|
@@ -148,6 +151,10 @@ class SynthesisQuantumFunctionCall(BaseModel):
|
|
148
151
|
description="The name of the function instance. "
|
149
152
|
"If not set, determined automatically.",
|
150
153
|
)
|
154
|
+
caller_parameters: Optional[list[str]] = pydantic.Field(default=None)
|
155
|
+
parameter_assignments: Optional[dict[str, ClassicalArg]] = pydantic.Field(
|
156
|
+
default=None
|
157
|
+
)
|
151
158
|
source_id: Optional[UUID] = pydantic.Field(default=None)
|
152
159
|
arithmetic_id: Optional[str] = pydantic.Field(default=None)
|
153
160
|
inverse_op_id: Optional[UUID] = pydantic.Field(default=None)
|