classiq 0.63.1__py3-none-any.whl → 0.65.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- classiq/_internals/api_wrapper.py +30 -0
- classiq/analyzer/url_utils.py +2 -3
- classiq/applications/chemistry/chemistry_model_constructor.py +8 -9
- classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +4 -6
- classiq/applications/combinatorial_optimization/combinatorial_problem.py +2 -5
- classiq/applications/finance/finance_model_constructor.py +7 -12
- classiq/applications/grover/grover_model_constructor.py +4 -6
- classiq/applications/qsvm/qsvm_model_constructor.py +6 -4
- classiq/execution/execution_session.py +14 -13
- classiq/interface/_version.py +1 -1
- classiq/interface/analyzer/result.py +1 -2
- classiq/interface/backend/backend_preferences.py +1 -9
- classiq/interface/executor/result.py +6 -3
- classiq/interface/generator/expressions/qmod_qarray_proxy.py +11 -13
- classiq/interface/generator/functions/type_name.py +6 -0
- classiq/interface/helpers/datastructures.py +26 -0
- classiq/interface/interface_version.py +1 -1
- classiq/interface/model/allocate.py +16 -0
- classiq/interface/model/handle_binding.py +11 -3
- classiq/interface/model/quantum_type.py +26 -0
- classiq/interface/model/statement_block.py +2 -0
- classiq/interface/server/routes.py +5 -0
- classiq/model_expansions/atomic_expression_functions_defs.py +6 -6
- classiq/model_expansions/capturing/captured_vars.py +27 -10
- classiq/model_expansions/evaluators/arg_type_match.py +4 -7
- classiq/model_expansions/evaluators/quantum_type_utils.py +25 -8
- classiq/model_expansions/expression_evaluator.py +8 -2
- classiq/model_expansions/function_builder.py +35 -11
- classiq/model_expansions/generative_functions.py +6 -4
- classiq/model_expansions/interpreters/__init__.py +0 -0
- classiq/model_expansions/interpreters/base_interpreter.py +263 -0
- classiq/model_expansions/interpreters/frontend_generative_interpreter.py +28 -0
- classiq/model_expansions/interpreters/generative_interpreter.py +249 -0
- classiq/model_expansions/model_tables.py +1 -92
- classiq/model_expansions/quantum_operations/__init__.py +0 -10
- classiq/model_expansions/quantum_operations/call_emitter.py +45 -93
- classiq/model_expansions/quantum_operations/declarative_call_emitter.py +87 -0
- classiq/model_expansions/quantum_operations/emitter.py +7 -2
- classiq/model_expansions/quantum_operations/quantum_function_call.py +11 -2
- classiq/model_expansions/quantum_operations/shallow_emitter.py +22 -3
- classiq/model_expansions/scope.py +15 -15
- classiq/model_expansions/scope_initialization.py +11 -5
- classiq/open_library/functions/discrete_sine_cosine_transform.py +8 -2
- classiq/open_library/functions/grover.py +1 -1
- classiq/open_library/functions/modular_exponentiation.py +8 -2
- classiq/open_library/functions/state_preparation.py +23 -13
- classiq/open_library/functions/swap_test.py +1 -2
- classiq/open_library/functions/variational.py +1 -2
- classiq/qmod/builtins/__init__.py +1 -1
- classiq/qmod/builtins/operations.py +51 -0
- classiq/qmod/declaration_inferrer.py +0 -3
- classiq/qmod/generative.py +4 -4
- classiq/qmod/native/pretty_printer.py +9 -1
- classiq/qmod/pretty_print/pretty_printer.py +12 -1
- classiq/qmod/qfunc.py +4 -2
- classiq/qmod/qmod_variable.py +55 -48
- classiq/qmod/quantum_function.py +7 -5
- classiq/qmod/semantics/annotation/__init__.py +0 -0
- classiq/qmod/semantics/annotation/call_annotation.py +92 -0
- classiq/qmod/semantics/lambdas.py +25 -0
- classiq/qmod/semantics/static_semantics_visitor.py +8 -46
- classiq/qmod/utilities.py +23 -1
- {classiq-0.63.1.dist-info → classiq-0.65.1.dist-info}/METADATA +1 -1
- {classiq-0.63.1.dist-info → classiq-0.65.1.dist-info}/RECORD +66 -67
- classiq/interface/helpers/dotdict.py +0 -18
- classiq/model_expansions/interpreter.py +0 -475
- classiq/model_expansions/quantum_operations/control.py +0 -290
- classiq/model_expansions/quantum_operations/expression_operation.py +0 -103
- classiq/model_expansions/quantum_operations/inplace_binary_operation.py +0 -535
- classiq/model_expansions/quantum_operations/invert.py +0 -36
- classiq/model_expansions/quantum_operations/phase.py +0 -187
- classiq/model_expansions/quantum_operations/power.py +0 -71
- classiq/model_expansions/quantum_operations/quantum_assignment_operation.py +0 -230
- classiq/model_expansions/quantum_operations/within_apply.py +0 -25
- classiq/qmod/semantics/annotation.py +0 -36
- /classiq/qmod/semantics/{qstruct_annotator.py → annotation/qstruct_annotator.py} +0 -0
- {classiq-0.63.1.dist-info → classiq-0.65.1.dist-info}/WHEEL +0 -0
@@ -22,6 +22,7 @@ from classiq.interface.execution.jobs import (
|
|
22
22
|
ExecutionJobDetailsV1,
|
23
23
|
ExecutionJobsQueryResultsV1,
|
24
24
|
)
|
25
|
+
from classiq.interface.execution.primitives import PrimitivesInput
|
25
26
|
from classiq.interface.executor import execution_request
|
26
27
|
from classiq.interface.generator import quantum_program as generator_result
|
27
28
|
from classiq.interface.hardware import HardwareInformation, Provider
|
@@ -120,6 +121,35 @@ class ApiWrapper:
|
|
120
121
|
)
|
121
122
|
return _parse_job_response(result, generator_result.QuantumProgram)
|
122
123
|
|
124
|
+
@classmethod
|
125
|
+
async def call_create_execution_session(
|
126
|
+
cls,
|
127
|
+
circuit: generator_result.QuantumProgram,
|
128
|
+
http_client: Optional[httpx.AsyncClient] = None,
|
129
|
+
) -> str:
|
130
|
+
raw_result = await cls._call_task_pydantic(
|
131
|
+
http_method=HTTPMethod.POST,
|
132
|
+
url=routes.EXECUTION_SESSIONS_PREFIX,
|
133
|
+
model=circuit,
|
134
|
+
http_client=http_client,
|
135
|
+
)
|
136
|
+
return raw_result["id"]
|
137
|
+
|
138
|
+
@classmethod
|
139
|
+
async def call_create_session_job(
|
140
|
+
cls,
|
141
|
+
session_id: str,
|
142
|
+
primitives_input: PrimitivesInput,
|
143
|
+
http_client: Optional[httpx.AsyncClient] = None,
|
144
|
+
) -> execution_request.ExecutionJobDetails:
|
145
|
+
data = await cls._call_task_pydantic(
|
146
|
+
http_method=HTTPMethod.POST,
|
147
|
+
url=routes.EXECUTION_SESSIONS_PREFIX + f"/{session_id}",
|
148
|
+
model=primitives_input,
|
149
|
+
http_client=http_client,
|
150
|
+
)
|
151
|
+
return execution_request.ExecutionJobDetails.model_validate(data)
|
152
|
+
|
123
153
|
@classmethod
|
124
154
|
async def call_convert_quantum_program(
|
125
155
|
cls,
|
classiq/analyzer/url_utils.py
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
import urllib
|
2
2
|
from urllib.parse import urljoin
|
3
|
-
from uuid import UUID
|
4
3
|
|
5
4
|
from classiq.interface.server import routes
|
6
5
|
|
@@ -21,7 +20,7 @@ def versioned_url_params(circuit_version: str) -> str:
|
|
21
20
|
)
|
22
21
|
|
23
22
|
|
24
|
-
def circuit_page_uri(circuit_id:
|
25
|
-
url = urljoin(f"{routes.ANALYZER_CIRCUIT_PAGE}/",
|
23
|
+
def circuit_page_uri(circuit_id: str, circuit_version: str) -> str:
|
24
|
+
url = urljoin(f"{routes.ANALYZER_CIRCUIT_PAGE}/", circuit_id)
|
26
25
|
url += versioned_url_params(circuit_version=circuit_version)
|
27
26
|
return url
|
@@ -7,6 +7,8 @@ from classiq.interface.chemistry.fermionic_operator import (
|
|
7
7
|
FermionicOperator,
|
8
8
|
SummedFermionicOperator,
|
9
9
|
)
|
10
|
+
from classiq.interface.model.allocate import Allocate
|
11
|
+
from classiq.interface.model.quantum_statement import QuantumStatement
|
10
12
|
from classiq.qmod.builtins.structs import (
|
11
13
|
MoleculeProblem as QmodMoleculeProblem,
|
12
14
|
Molecule as QmodMolecule,
|
@@ -441,16 +443,13 @@ def _get_chemistry_quantum_main(
|
|
441
443
|
use_hartree_fock: bool,
|
442
444
|
ansatz_parameters: AnsatzParameters,
|
443
445
|
) -> NativeFunctionDefinition:
|
444
|
-
body = []
|
446
|
+
body: list[QuantumStatement] = []
|
445
447
|
body.append(
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
),
|
452
|
-
HandleBinding(name="qbv"),
|
453
|
-
],
|
448
|
+
Allocate(
|
449
|
+
size=Expression(
|
450
|
+
expr=f"get_field(get_field({_get_problem_to_hamiltonian_name(chemistry_problem)}({_convert_library_problem_to_qmod_problem(chemistry_problem)})[0], 'pauli'), 'len')"
|
451
|
+
),
|
452
|
+
target=HandleBinding(name="qbv"),
|
454
453
|
),
|
455
454
|
)
|
456
455
|
if use_hartree_fock:
|
classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py
CHANGED
@@ -14,6 +14,7 @@ from classiq.interface.generator.functions.port_declaration import (
|
|
14
14
|
PortDeclarationDirection,
|
15
15
|
)
|
16
16
|
from classiq.interface.generator.functions.type_name import Struct
|
17
|
+
from classiq.interface.model.allocate import Allocate
|
17
18
|
from classiq.interface.model.classical_parameter_declaration import (
|
18
19
|
ClassicalParameterDeclaration,
|
19
20
|
)
|
@@ -89,12 +90,9 @@ def construct_combi_opt_py_model(
|
|
89
90
|
),
|
90
91
|
],
|
91
92
|
body=[
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
Expression(expr="get_field(target, 'len')"),
|
96
|
-
HandleBinding(name="target"),
|
97
|
-
],
|
93
|
+
Allocate(
|
94
|
+
size=Expression(expr="get_field(target, 'len')"),
|
95
|
+
target=HandleBinding(name="target"),
|
98
96
|
),
|
99
97
|
QuantumFunctionCall(
|
100
98
|
function="qaoa_penalty",
|
@@ -21,11 +21,8 @@ from classiq.open_library.functions.utility_functions import (
|
|
21
21
|
apply_to_all,
|
22
22
|
hadamard_transform,
|
23
23
|
)
|
24
|
-
from classiq.qmod.builtins.functions import
|
25
|
-
|
26
|
-
allocate,
|
27
|
-
)
|
28
|
-
from classiq.qmod.builtins.operations import phase, repeat
|
24
|
+
from classiq.qmod.builtins.functions import RX
|
25
|
+
from classiq.qmod.builtins.operations import allocate, phase, repeat
|
29
26
|
from classiq.qmod.cparam import CReal
|
30
27
|
from classiq.qmod.create_model_function import create_model
|
31
28
|
from classiq.qmod.qfunc import qfunc
|
@@ -9,6 +9,7 @@ from classiq.interface.generator.expressions.expression import Expression
|
|
9
9
|
from classiq.interface.generator.functions.port_declaration import (
|
10
10
|
PortDeclarationDirection,
|
11
11
|
)
|
12
|
+
from classiq.interface.model.allocate import Allocate
|
12
13
|
from classiq.interface.model.handle_binding import HandleBinding
|
13
14
|
from classiq.interface.model.model import Model, SerializedModel
|
14
15
|
from classiq.interface.model.native_function_definition import NativeFunctionDefinition
|
@@ -78,19 +79,13 @@ def construct_finance_model(
|
|
78
79
|
],
|
79
80
|
body=[
|
80
81
|
VariableDeclarationStatement(name="unitary_port"),
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
Expression(expr=f"{num_unitary_qubits}"),
|
85
|
-
HandleBinding(name="unitary_port"),
|
86
|
-
],
|
82
|
+
Allocate(
|
83
|
+
size=Expression(expr=f"{num_unitary_qubits}"),
|
84
|
+
target=HandleBinding(name="unitary_port"),
|
87
85
|
),
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
Expression(expr=f"{phase_port_size}"),
|
92
|
-
HandleBinding(name="phase_port"),
|
93
|
-
],
|
86
|
+
Allocate(
|
87
|
+
size=Expression(expr=f"{phase_port_size}"),
|
88
|
+
target=HandleBinding(name="phase_port"),
|
94
89
|
),
|
95
90
|
QuantumFunctionCall(
|
96
91
|
function="qmci",
|
@@ -2,6 +2,7 @@ from classiq.interface.generator.expressions.expression import Expression
|
|
2
2
|
from classiq.interface.generator.functions.port_declaration import (
|
3
3
|
PortDeclarationDirection,
|
4
4
|
)
|
5
|
+
from classiq.interface.model.allocate import Allocate
|
5
6
|
from classiq.interface.model.bind_operation import BindOperation
|
6
7
|
from classiq.interface.model.handle_binding import HandleBinding, SlicedHandleBinding
|
7
8
|
from classiq.interface.model.model import Model, SerializedModel
|
@@ -121,12 +122,9 @@ def construct_grover_model(
|
|
121
122
|
),
|
122
123
|
body=[
|
123
124
|
VariableDeclarationStatement(name="packed_vars"),
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
Expression(expr=f"{num_qubits}"),
|
128
|
-
HandleBinding(name="packed_vars"),
|
129
|
-
],
|
125
|
+
Allocate(
|
126
|
+
size=Expression(expr=f"{num_qubits}"),
|
127
|
+
target=HandleBinding(name="packed_vars"),
|
130
128
|
),
|
131
129
|
QuantumFunctionCall(
|
132
130
|
function="grover_search",
|
@@ -6,11 +6,13 @@ from classiq.interface.generator.expressions.expression import Expression
|
|
6
6
|
from classiq.interface.generator.functions.port_declaration import (
|
7
7
|
PortDeclarationDirection,
|
8
8
|
)
|
9
|
+
from classiq.interface.model.allocate import Allocate
|
9
10
|
from classiq.interface.model.handle_binding import HandleBinding
|
10
11
|
from classiq.interface.model.model import Model, SerializedModel
|
11
12
|
from classiq.interface.model.native_function_definition import NativeFunctionDefinition
|
12
13
|
from classiq.interface.model.port_declaration import PortDeclaration
|
13
14
|
from classiq.interface.model.quantum_function_call import QuantumFunctionCall
|
15
|
+
from classiq.interface.model.quantum_statement import QuantumStatement
|
14
16
|
|
15
17
|
from classiq.qmod.builtins.enums import Pauli, QSVMFeatureMapEntanglement
|
16
18
|
from classiq.qmod.utilities import qmod_val_to_expr_str
|
@@ -61,7 +63,7 @@ def _pauli_feature_map_function_params(
|
|
61
63
|
|
62
64
|
def get_qsvm_qmain_body(
|
63
65
|
feature_map_function_name: str, **kwargs: Any
|
64
|
-
) -> list[
|
66
|
+
) -> list[QuantumStatement]:
|
65
67
|
if feature_map_function_name == "bloch_sphere_feature_map":
|
66
68
|
params, size_expr = _bloch_sphere_feature_map_function_params(**kwargs)
|
67
69
|
elif feature_map_function_name == "pauli_feature_map":
|
@@ -70,9 +72,9 @@ def get_qsvm_qmain_body(
|
|
70
72
|
raise ClassiqValueError(INVALID_FEATURE_MAP_FUNC_NAME_MSG)
|
71
73
|
|
72
74
|
return [
|
73
|
-
|
74
|
-
|
75
|
-
|
75
|
+
Allocate(
|
76
|
+
size=Expression(expr=size_expr),
|
77
|
+
target=HandleBinding(name="qbv"),
|
76
78
|
),
|
77
79
|
QuantumFunctionCall(
|
78
80
|
function=feature_map_function_name,
|
@@ -1,6 +1,5 @@
|
|
1
1
|
import json
|
2
2
|
import random
|
3
|
-
from functools import cached_property
|
4
3
|
from types import TracebackType
|
5
4
|
from typing import Callable, Optional, Union, cast
|
6
5
|
|
@@ -110,6 +109,8 @@ class ExecutionSession:
|
|
110
109
|
|
111
110
|
self._async_client = client().async_client()
|
112
111
|
|
112
|
+
self._session_id: str | None = None
|
113
|
+
|
113
114
|
def __enter__(self) -> "ExecutionSession":
|
114
115
|
return self
|
115
116
|
|
@@ -127,22 +128,22 @@ class ExecutionSession:
|
|
127
128
|
"""
|
128
129
|
async_utils.run(self._async_client.aclose())
|
129
130
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
131
|
+
def get_session_id(self) -> str:
|
132
|
+
if self._session_id is None:
|
133
|
+
self._session_id = async_utils.run(
|
134
|
+
ApiWrapper.call_create_execution_session(
|
135
|
+
self.program, self._async_client
|
136
|
+
)
|
137
|
+
)
|
138
|
+
return self._session_id
|
135
139
|
|
136
140
|
def _execute(self, primitives_input: PrimitivesInput) -> ExecutionJob:
|
137
141
|
primitives_input.random_seed = self._random_seed
|
138
142
|
self._random_seed = self._rng.randint(0, 2**32 - 1)
|
139
|
-
execution_input = self._execution_input.copy()
|
140
|
-
# The use of `model_dump_json` is necessary for complex numbers serialization
|
141
|
-
execution_input["primitives_input"] = json.loads(
|
142
|
-
primitives_input.model_dump_json()
|
143
|
-
)
|
144
143
|
result = async_utils.run(
|
145
|
-
ApiWrapper.
|
144
|
+
ApiWrapper.call_create_session_job(
|
145
|
+
self.get_session_id(), primitives_input, self._async_client
|
146
|
+
)
|
146
147
|
)
|
147
148
|
return ExecutionJob(details=result)
|
148
149
|
|
@@ -360,7 +361,7 @@ class ExecutionSession:
|
|
360
361
|
output_name: The name of the register to filter
|
361
362
|
condition: Filter out values of the statevector for which this callable is False
|
362
363
|
"""
|
363
|
-
if
|
364
|
+
if self._session_id is not None:
|
364
365
|
raise ClassiqError(
|
365
366
|
"set_measured_state_filter must be called before use of the first primitive (sample, estimate...)"
|
366
367
|
)
|
classiq/interface/_version.py
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
from typing import Annotated, Literal, Optional, Union
|
2
|
-
from uuid import UUID
|
3
2
|
|
4
3
|
import pydantic
|
5
4
|
from pydantic import Field
|
@@ -34,7 +33,7 @@ class RbResults(VersionedModel):
|
|
34
33
|
|
35
34
|
|
36
35
|
class DataID(pydantic.BaseModel):
|
37
|
-
id:
|
36
|
+
id: str
|
38
37
|
|
39
38
|
|
40
39
|
class QasmCode(pydantic.BaseModel):
|
@@ -22,7 +22,7 @@ from classiq.interface.backend.quantum_backend_providers import (
|
|
22
22
|
ProviderTypeVendor,
|
23
23
|
ProviderVendor,
|
24
24
|
)
|
25
|
-
from classiq.interface.exceptions import ClassiqDeprecationWarning
|
25
|
+
from classiq.interface.exceptions import ClassiqDeprecationWarning
|
26
26
|
from classiq.interface.hardware import Provider
|
27
27
|
|
28
28
|
|
@@ -225,14 +225,6 @@ class AwsBackendPreferences(BackendPreferences):
|
|
225
225
|
description="Run through Classiq's credentials while using user's allocated budget.",
|
226
226
|
)
|
227
227
|
|
228
|
-
@pydantic.field_validator("s3_bucket_name", mode="before")
|
229
|
-
@classmethod
|
230
|
-
def _validate_s3_bucket_name(cls, s3_bucket_name: str) -> str:
|
231
|
-
s3_bucket_name = s3_bucket_name.strip()
|
232
|
-
if not s3_bucket_name.startswith("amazon-braket-"):
|
233
|
-
raise ClassiqValueError('S3 bucket name should start with "amazon-braket-"')
|
234
|
-
return s3_bucket_name
|
235
|
-
|
236
228
|
|
237
229
|
class IBMBackendProvider(BaseModel):
|
238
230
|
"""
|
@@ -20,7 +20,7 @@ from classiq.interface.generator.arith import number_utils
|
|
20
20
|
from classiq.interface.generator.complex_type import Complex
|
21
21
|
from classiq.interface.generator.functions.classical_type import QmodPyObject
|
22
22
|
from classiq.interface.helpers.custom_pydantic_types import PydanticNonNegIntTuple
|
23
|
-
from classiq.interface.helpers.
|
23
|
+
from classiq.interface.helpers.datastructures import get_sdk_compatible_python_object
|
24
24
|
from classiq.interface.helpers.versioned_model import VersionedModel
|
25
25
|
|
26
26
|
_ILLEGAL_QUBIT_ERROR_MSG: str = "Illegal qubit index requested"
|
@@ -51,8 +51,11 @@ class SampledState(BaseModel):
|
|
51
51
|
|
52
52
|
@pydantic.field_validator("state", mode="after")
|
53
53
|
@classmethod
|
54
|
-
def
|
55
|
-
return {
|
54
|
+
def _make_state_sdk_compatible(cls, state: ParsedState) -> DotAccessParsedState:
|
55
|
+
return {
|
56
|
+
name: get_sdk_compatible_python_object(value)
|
57
|
+
for name, value in state.items()
|
58
|
+
}
|
56
59
|
|
57
60
|
|
58
61
|
ParsedCounts: TypeAlias = list[SampledState]
|
@@ -3,7 +3,10 @@ from typing import TYPE_CHECKING, Any, Union
|
|
3
3
|
|
4
4
|
from sympy import Integer
|
5
5
|
|
6
|
-
from classiq.interface.exceptions import
|
6
|
+
from classiq.interface.exceptions import (
|
7
|
+
ClassiqInternalExpansionError,
|
8
|
+
ClassiqValueError,
|
9
|
+
)
|
7
10
|
from classiq.interface.generator.expressions.expression import Expression
|
8
11
|
from classiq.interface.generator.expressions.non_symbolic_expr import NonSymbolicExpr
|
9
12
|
from classiq.interface.generator.expressions.qmod_sized_proxy import QmodSizedProxy
|
@@ -18,12 +21,7 @@ if TYPE_CHECKING:
|
|
18
21
|
|
19
22
|
|
20
23
|
ILLEGAL_SLICING_STEP_MSG = "Slicing with a step of a quantum variable is not supported"
|
21
|
-
SLICE_OUT_OF_BOUNDS_MSG = "Slice indices out of bounds"
|
22
|
-
SUBSCRIPT_OUT_OF_BOUNDS_MSG = "Subscript index out of bounds"
|
23
24
|
ILLEGAL_SLICE_MSG = "Quantum array slice must be of the form [<int-value>:<int-value>]."
|
24
|
-
ILLEGAL_SLICE_BOUNDS_MSG = (
|
25
|
-
"The quantum array slice start value ({}) must be lower than its stop value ({})."
|
26
|
-
)
|
27
25
|
|
28
26
|
|
29
27
|
class QmodQArrayProxy(NonSymbolicExpr, QmodSizedProxy):
|
@@ -48,7 +46,7 @@ class QmodQArrayProxy(NonSymbolicExpr, QmodSizedProxy):
|
|
48
46
|
if isinstance(index, Integer):
|
49
47
|
index = int(index)
|
50
48
|
if index < 0 or index >= self._length:
|
51
|
-
raise
|
49
|
+
raise ClassiqInternalExpansionError
|
52
50
|
|
53
51
|
return self._element_type.get_proxy(
|
54
52
|
SubscriptHandleBinding(
|
@@ -66,12 +64,12 @@ class QmodQArrayProxy(NonSymbolicExpr, QmodSizedProxy):
|
|
66
64
|
slice_ = slice(slice_.start, int(slice_.stop))
|
67
65
|
if not isinstance(slice_.start, int) or not isinstance(slice_.stop, int):
|
68
66
|
raise ClassiqValueError(ILLEGAL_SLICE_MSG)
|
69
|
-
if
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
raise
|
67
|
+
if (
|
68
|
+
slice_.start >= slice_.stop
|
69
|
+
or slice_.start < 0
|
70
|
+
or slice_.stop > self._length
|
71
|
+
):
|
72
|
+
raise ClassiqInternalExpansionError
|
75
73
|
|
76
74
|
return QmodQArrayProxy(
|
77
75
|
SlicedHandleBinding(
|
@@ -75,6 +75,12 @@ class TypeName(ClassicalType, QuantumType):
|
|
75
75
|
field_type.is_instantiated for field_type in self.fields.values()
|
76
76
|
)
|
77
77
|
|
78
|
+
@property
|
79
|
+
def is_evaluated(self) -> bool:
|
80
|
+
return self.has_fields and all(
|
81
|
+
field_type.is_evaluated for field_type in self.fields.values()
|
82
|
+
)
|
83
|
+
|
78
84
|
|
79
85
|
class Enum(TypeName):
|
80
86
|
pass
|
@@ -0,0 +1,26 @@
|
|
1
|
+
from typing import Any
|
2
|
+
|
3
|
+
|
4
|
+
class DotDict(dict):
|
5
|
+
def __getattr__(self, key: str) -> Any:
|
6
|
+
return super().get(key)
|
7
|
+
|
8
|
+
def __setattr__(self, key: str, value: Any) -> None:
|
9
|
+
super().__setitem__(key, value)
|
10
|
+
|
11
|
+
def __delattr__(self, key: str) -> None:
|
12
|
+
super().__delitem__(key)
|
13
|
+
|
14
|
+
|
15
|
+
class LenList(list):
|
16
|
+
@property
|
17
|
+
def len(self) -> int:
|
18
|
+
return len(self)
|
19
|
+
|
20
|
+
|
21
|
+
def get_sdk_compatible_python_object(obj: Any) -> Any:
|
22
|
+
if isinstance(obj, list):
|
23
|
+
return LenList([get_sdk_compatible_python_object(item) for item in obj])
|
24
|
+
if isinstance(obj, dict):
|
25
|
+
return DotDict({k: get_sdk_compatible_python_object(v) for k, v in obj.items()})
|
26
|
+
return obj
|
@@ -1 +1 @@
|
|
1
|
-
INTERFACE_VERSION = "
|
1
|
+
INTERFACE_VERSION = "7"
|
@@ -0,0 +1,16 @@
|
|
1
|
+
from collections.abc import Mapping
|
2
|
+
from typing import Literal, Optional
|
3
|
+
|
4
|
+
from classiq.interface.generator.expressions.expression import Expression
|
5
|
+
from classiq.interface.model.handle_binding import ConcreteHandleBinding, HandleBinding
|
6
|
+
from classiq.interface.model.quantum_statement import QuantumOperation
|
7
|
+
|
8
|
+
|
9
|
+
class Allocate(QuantumOperation):
|
10
|
+
kind: Literal["Allocate"]
|
11
|
+
size: Optional[Expression] = None
|
12
|
+
target: ConcreteHandleBinding
|
13
|
+
|
14
|
+
@property
|
15
|
+
def wiring_outputs(self) -> Mapping[str, HandleBinding]:
|
16
|
+
return {"out": self.target}
|
@@ -243,15 +243,23 @@ class SlicedHandleBinding(NestedHandleBinding):
|
|
243
243
|
def _get_collapsed_stop(self) -> Expression:
|
244
244
|
if TYPE_CHECKING:
|
245
245
|
assert isinstance(self.base_handle, SlicedHandleBinding)
|
246
|
-
if self.
|
246
|
+
if self._is_evaluated() and self.base_handle.start.is_evaluated():
|
247
247
|
return Expression(
|
248
|
-
expr=str(
|
248
|
+
expr=str(
|
249
|
+
self.end.to_int_value()
|
250
|
+
- self.start.to_int_value()
|
251
|
+
+ self.base_handle.start.to_int_value()
|
252
|
+
)
|
249
253
|
)
|
250
|
-
return Expression(
|
254
|
+
return Expression(
|
255
|
+
expr=f"({self.end})-({self.start})+({self.base_handle.start})"
|
256
|
+
)
|
251
257
|
|
252
258
|
def replace_prefix(
|
253
259
|
self, prefix: HandleBinding, replacement: HandleBinding
|
254
260
|
) -> HandleBinding:
|
261
|
+
if self == prefix:
|
262
|
+
return replacement
|
255
263
|
if (
|
256
264
|
isinstance(prefix, SlicedHandleBinding)
|
257
265
|
and self.base_handle == prefix.base_handle
|
@@ -63,6 +63,10 @@ class QuantumType(HashableASTNode):
|
|
63
63
|
def is_instantiated(self) -> bool:
|
64
64
|
raise NotImplementedError
|
65
65
|
|
66
|
+
@property
|
67
|
+
def is_evaluated(self) -> bool:
|
68
|
+
raise NotImplementedError
|
69
|
+
|
66
70
|
|
67
71
|
class QuantumScalar(QuantumType):
|
68
72
|
def get_proxy(self, handle: "HandleBinding") -> QmodQScalarProxy:
|
@@ -96,6 +100,10 @@ class QuantumBit(QuantumScalar):
|
|
96
100
|
def is_instantiated(self) -> bool:
|
97
101
|
return True
|
98
102
|
|
103
|
+
@property
|
104
|
+
def is_evaluated(self) -> bool:
|
105
|
+
return True
|
106
|
+
|
99
107
|
|
100
108
|
class QuantumBitvector(QuantumType):
|
101
109
|
element_type: "ConcreteQuantumType" = Field(
|
@@ -154,6 +162,14 @@ class QuantumBitvector(QuantumType):
|
|
154
162
|
def is_instantiated(self) -> bool:
|
155
163
|
return self.length is not None and self.element_type.is_instantiated
|
156
164
|
|
165
|
+
@property
|
166
|
+
def is_evaluated(self) -> bool:
|
167
|
+
return (
|
168
|
+
self.length is not None
|
169
|
+
and self.length.is_evaluated()
|
170
|
+
and self.element_type.is_evaluated
|
171
|
+
)
|
172
|
+
|
157
173
|
|
158
174
|
class QuantumNumeric(QuantumScalar):
|
159
175
|
kind: Literal["qnum"]
|
@@ -227,6 +243,16 @@ class QuantumNumeric(QuantumScalar):
|
|
227
243
|
def is_instantiated(self) -> bool:
|
228
244
|
return self.size is not None
|
229
245
|
|
246
|
+
@property
|
247
|
+
def is_evaluated(self) -> bool:
|
248
|
+
if self.size is None or not self.size.is_evaluated():
|
249
|
+
return False
|
250
|
+
if self.is_signed is not None and not self.is_signed.is_evaluated():
|
251
|
+
return False
|
252
|
+
return not (
|
253
|
+
self.fraction_digits is not None and not self.fraction_digits.is_evaluated()
|
254
|
+
)
|
255
|
+
|
230
256
|
|
231
257
|
class RegisterQuantumType(BaseModel):
|
232
258
|
quantum_types: "ConcreteQuantumType"
|
@@ -2,6 +2,7 @@ from typing import Annotated, Union
|
|
2
2
|
|
3
3
|
from pydantic import Field
|
4
4
|
|
5
|
+
from classiq.interface.model.allocate import Allocate
|
5
6
|
from classiq.interface.model.bind_operation import BindOperation
|
6
7
|
from classiq.interface.model.classical_if import ClassicalIf
|
7
8
|
from classiq.interface.model.control import Control
|
@@ -26,6 +27,7 @@ from classiq.interface.model.within_apply_operation import WithinApply
|
|
26
27
|
|
27
28
|
ConcreteQuantumStatement = Annotated[
|
28
29
|
Union[
|
30
|
+
Allocate,
|
29
31
|
QuantumFunctionCall,
|
30
32
|
ArithmeticOperation,
|
31
33
|
AmplitudeLoadingOperation,
|
@@ -1,6 +1,7 @@
|
|
1
1
|
ANALYZER_PREFIX = "/analyzer"
|
2
2
|
CHEMISTRY_PREFIX = "/chemistry"
|
3
3
|
EXECUTION_PREFIX = "/execution"
|
4
|
+
EXECUTION_SESSIONS_PREFIX = EXECUTION_PREFIX + "/sessions"
|
4
5
|
CONVERSION_PREFIX = "/conversion"
|
5
6
|
PROVIDERS_PREFIX = "/providers"
|
6
7
|
|
@@ -24,12 +25,16 @@ TASKS_SUFFIX = "/tasks"
|
|
24
25
|
RB = "/rb"
|
25
26
|
ANALYZER_DATA_TASK = f"{TASKS_SUFFIX}/data"
|
26
27
|
ANALYZER_QASM_TASK = f"{TASKS_SUFFIX}/qasm"
|
28
|
+
ANALYZER_GET_VISUAL_MODEL = "/get_visual_model"
|
29
|
+
ANALYZER_GET_IDE_DATA = "/get_ide_data"
|
27
30
|
IDE_EVENT_TASK = f"{TASKS_SUFFIX}/event"
|
28
31
|
DATA_DOG_EVENT_TASK = f"{TASKS_SUFFIX}/data_dog_event"
|
29
32
|
|
30
33
|
ANALYZER_DATA_TASK_UPLOAD_FILE = f"{TASKS_SUFFIX}/data/file_upload"
|
31
34
|
ANALYZER_DATA_FULL_PATH = f"{ANALYZER_PREFIX}{ANALYZER_DATA_TASK}"
|
32
35
|
ANALYZER_QASM_FULL_PATH = f"{ANALYZER_PREFIX}{ANALYZER_QASM_TASK}"
|
36
|
+
ANALYZER_GET_VISUAL_MODEL_FULL_PATH = f"{ANALYZER_PREFIX}{ANALYZER_GET_VISUAL_MODEL}"
|
37
|
+
ANALYZER_GET_IDE_DATA_FULL_PATH = f"{ANALYZER_PREFIX}{ANALYZER_GET_IDE_DATA}"
|
33
38
|
IDE_EVENT_TASK_FULL_PATH = f"{ANALYZER_PREFIX}{IDE_EVENT_TASK}"
|
34
39
|
DATA_DOG_EVENT_TASK_FULL_PATH = f"{ANALYZER_PREFIX}{DATA_DOG_EVENT_TASK}"
|
35
40
|
|
@@ -33,7 +33,6 @@ from classiq.interface.generator.functions.type_name import TypeName
|
|
33
33
|
from classiq.model_expansions.model_tables import (
|
34
34
|
HandleIdentifier,
|
35
35
|
HandleTable,
|
36
|
-
SymbolTable,
|
37
36
|
)
|
38
37
|
from classiq.model_expansions.sympy_conversion.arithmetics import (
|
39
38
|
BitwiseAnd,
|
@@ -48,13 +47,14 @@ from classiq.model_expansions.sympy_conversion.expression_to_sympy import (
|
|
48
47
|
from classiq.model_expansions.sympy_conversion.sympy_to_python import (
|
49
48
|
sympy_to_python,
|
50
49
|
)
|
50
|
+
from classiq.qmod.model_state_container import QMODULE
|
51
51
|
|
52
52
|
|
53
53
|
def qmod_val_to_python(val: ExpressionValue, qmod_type: ClassicalType) -> Any:
|
54
54
|
if isinstance(qmod_type, TypeName):
|
55
55
|
if (
|
56
56
|
isinstance(val, QmodStructInstance)
|
57
|
-
and val.struct_declaration ==
|
57
|
+
and val.struct_declaration == QMODULE.type_decls[qmod_type.name]
|
58
58
|
):
|
59
59
|
return {
|
60
60
|
field_name: qmod_val_to_python(val.fields[field_name], field_type)
|
@@ -97,10 +97,10 @@ def qmod_val_to_python(val: ExpressionValue, qmod_type: ClassicalType) -> Any:
|
|
97
97
|
|
98
98
|
def python_val_to_qmod(val: Any, qmod_type: ClassicalType) -> ExpressionValue:
|
99
99
|
if isinstance(qmod_type, TypeName):
|
100
|
-
if qmod_type.name in
|
100
|
+
if qmod_type.name in QMODULE.enum_decls:
|
101
101
|
return val
|
102
102
|
|
103
|
-
struct_decl =
|
103
|
+
struct_decl = QMODULE.type_decls[qmod_type.name]
|
104
104
|
if not isinstance(val, Mapping):
|
105
105
|
raise ClassiqInternalExpansionError(
|
106
106
|
f"Bad value for struct {struct_decl.name}"
|
@@ -138,7 +138,7 @@ def python_call_wrapper(func: Callable, *args: ExpressionValue) -> Any:
|
|
138
138
|
|
139
139
|
def struct_literal(struct_type_symbol: Symbol, **kwargs: Any) -> QmodStructInstance:
|
140
140
|
return QmodStructInstance(
|
141
|
-
|
141
|
+
QMODULE.type_decls[struct_type_symbol.name],
|
142
142
|
{field: sympy_to_python(field_value) for field, field_value in kwargs.items()},
|
143
143
|
)
|
144
144
|
|
@@ -179,7 +179,7 @@ def get_field(
|
|
179
179
|
|
180
180
|
|
181
181
|
def get_type(struct_type: Symbol) -> TypeProxy:
|
182
|
-
return TypeProxy(
|
182
|
+
return TypeProxy(QMODULE.type_decls[struct_type.name])
|
183
183
|
|
184
184
|
|
185
185
|
def _unwrap_sympy_numeric(n: Any) -> Any:
|