classiq 0.51.1__py3-none-any.whl → 0.53.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/_internals/api_wrapper.py +47 -15
- classiq/_internals/authentication/auth0.py +20 -4
- classiq/_internals/authentication/password_manager.py +16 -4
- classiq/_internals/client.py +3 -3
- classiq/_internals/host_checker.py +5 -3
- classiq/_internals/jobs.py +3 -3
- classiq/analyzer/analyzer_utilities.py +1 -1
- classiq/applications/chemistry/ground_state_problem.py +1 -1
- classiq/applications/combinatorial_helpers/pyomo_utils.py +3 -1
- classiq/applications/qnn/gradients/quantum_gradient.py +1 -1
- classiq/applications/qnn/qlayer.py +25 -6
- classiq/execution/__init__.py +5 -0
- classiq/execution/execution_session.py +43 -2
- classiq/execution/iqcc.py +63 -0
- classiq/execution/jobs.py +2 -2
- classiq/execution/qaoa.py +84 -0
- classiq/executor.py +3 -3
- classiq/interface/_version.py +1 -1
- classiq/interface/analyzer/analysis_params.py +19 -9
- classiq/interface/analyzer/cytoscape_graph.py +10 -3
- classiq/interface/analyzer/result.py +6 -5
- classiq/interface/applications/qsvm.py +13 -12
- classiq/interface/backend/backend_preferences.py +78 -105
- classiq/interface/backend/ionq/ionq_quantum_program.py +12 -19
- classiq/interface/backend/pydantic_backend.py +24 -12
- classiq/interface/backend/quantum_backend_providers.py +2 -0
- classiq/interface/chemistry/fermionic_operator.py +7 -7
- classiq/interface/chemistry/ground_state_problem.py +23 -18
- classiq/interface/chemistry/molecule.py +10 -5
- classiq/interface/chemistry/operator.py +71 -44
- classiq/interface/combinatorial_optimization/mht_qaoa_input.py +2 -1
- classiq/interface/debug_info/debug_info.py +3 -4
- classiq/interface/exceptions.py +3 -1
- classiq/interface/execution/iqcc.py +19 -0
- classiq/interface/execution/jobs.py +10 -10
- classiq/interface/executor/aws_execution_cost.py +37 -20
- classiq/interface/executor/execution_preferences.py +1 -2
- classiq/interface/executor/execution_request.py +2 -2
- classiq/interface/executor/execution_result.py +4 -2
- classiq/interface/executor/iqae_result.py +1 -1
- classiq/interface/executor/optimizer_preferences.py +14 -10
- classiq/interface/executor/quantum_code.py +21 -16
- classiq/interface/executor/register_initialization.py +10 -10
- classiq/interface/executor/result.py +31 -17
- classiq/interface/executor/vqe_result.py +1 -1
- classiq/interface/finance/function_input.py +27 -18
- classiq/interface/finance/log_normal_model_input.py +2 -2
- classiq/interface/finance/model_input.py +3 -2
- classiq/interface/generator/amplitude_loading.py +8 -6
- classiq/interface/generator/arith/argument_utils.py +24 -0
- classiq/interface/generator/arith/arithmetic.py +5 -3
- classiq/interface/generator/arith/arithmetic_expression_abc.py +36 -14
- classiq/interface/generator/arith/arithmetic_operations.py +6 -3
- classiq/interface/generator/arith/binary_ops.py +88 -63
- classiq/interface/generator/arith/extremum_operations.py +22 -13
- classiq/interface/generator/arith/logical_ops.py +6 -4
- classiq/interface/generator/arith/number_utils.py +3 -3
- classiq/interface/generator/arith/register_user_input.py +32 -17
- classiq/interface/generator/arith/unary_ops.py +5 -4
- classiq/interface/generator/chemistry_function_params.py +2 -1
- classiq/interface/generator/circuit_code/circuit_code.py +2 -1
- classiq/interface/generator/commuting_pauli_exponentiation.py +6 -5
- classiq/interface/generator/complex_type.py +14 -18
- classiq/interface/generator/control_state.py +32 -26
- classiq/interface/generator/expressions/expression.py +6 -5
- classiq/interface/generator/function_params.py +22 -39
- classiq/interface/generator/functions/classical_function_declaration.py +1 -1
- classiq/interface/generator/functions/classical_type.py +32 -23
- classiq/interface/generator/functions/concrete_types.py +8 -7
- classiq/interface/generator/functions/function_declaration.py +4 -5
- classiq/interface/generator/functions/type_name.py +5 -4
- classiq/interface/generator/generated_circuit_data.py +9 -6
- classiq/interface/generator/grover_diffuser.py +26 -18
- classiq/interface/generator/grover_operator.py +32 -22
- classiq/interface/generator/hamiltonian_evolution/exponentiation.py +3 -4
- classiq/interface/generator/hamiltonian_evolution/qdrift.py +4 -4
- classiq/interface/generator/hamiltonian_evolution/suzuki_trotter.py +8 -7
- classiq/interface/generator/hardware/hardware_data.py +27 -26
- classiq/interface/generator/hardware_efficient_ansatz.py +11 -6
- classiq/interface/generator/hartree_fock.py +2 -1
- classiq/interface/generator/identity.py +7 -2
- classiq/interface/generator/linear_pauli_rotations.py +27 -14
- classiq/interface/generator/mcu.py +15 -12
- classiq/interface/generator/mcx.py +18 -10
- classiq/interface/generator/model/constraints.py +4 -2
- classiq/interface/generator/model/model.py +2 -1
- classiq/interface/generator/model/preferences/preferences.py +30 -32
- classiq/interface/generator/oracles/custom_oracle.py +13 -10
- classiq/interface/generator/piecewise_linear_amplitude_loading.py +37 -21
- classiq/interface/generator/qpe.py +38 -26
- classiq/interface/generator/qsvm.py +4 -4
- classiq/interface/generator/quantum_function_call.py +57 -44
- classiq/interface/generator/quantum_program.py +8 -6
- classiq/interface/generator/range_types.py +10 -11
- classiq/interface/generator/standard_gates/controlled_standard_gates.py +9 -5
- classiq/interface/generator/standard_gates/standard_angle_metaclass.py +2 -6
- classiq/interface/generator/standard_gates/u_gate.py +7 -10
- classiq/interface/generator/state_preparation/computational_basis_state_preparation.py +2 -1
- classiq/interface/generator/state_preparation/distributions.py +12 -12
- classiq/interface/generator/state_preparation/state_preparation.py +22 -16
- classiq/interface/generator/types/enum_declaration.py +2 -1
- classiq/interface/generator/ucc.py +2 -1
- classiq/interface/generator/unitary_gate.py +2 -1
- classiq/interface/generator/user_defined_function_params.py +3 -0
- classiq/interface/generator/visitor.py +1 -1
- classiq/interface/hardware.py +18 -3
- classiq/interface/helpers/custom_pydantic_types.py +38 -47
- classiq/interface/helpers/dotdict.py +18 -0
- classiq/interface/helpers/pydantic_model_helpers.py +3 -2
- classiq/interface/helpers/versioned_model.py +1 -4
- classiq/interface/ide/ide_data.py +5 -5
- classiq/interface/ide/visual_model.py +18 -5
- classiq/interface/interface_version.py +1 -1
- classiq/interface/jobs.py +12 -22
- classiq/interface/model/bind_operation.py +2 -1
- classiq/interface/model/classical_parameter_declaration.py +10 -4
- classiq/interface/model/handle_binding.py +20 -24
- classiq/interface/model/inplace_binary_operation.py +16 -9
- classiq/interface/model/model.py +21 -11
- classiq/interface/model/native_function_definition.py +10 -0
- classiq/interface/model/port_declaration.py +10 -7
- classiq/interface/model/quantum_expressions/arithmetic_operation.py +6 -4
- classiq/interface/model/quantum_function_declaration.py +22 -11
- classiq/interface/model/quantum_statement.py +6 -7
- classiq/interface/model/quantum_type.py +22 -19
- classiq/interface/model/statement_block.py +9 -9
- classiq/interface/server/global_versions.py +4 -5
- classiq/interface/server/routes.py +8 -0
- classiq/model_expansions/evaluators/parameter_types.py +3 -3
- classiq/model_expansions/expression_renamer.py +1 -1
- classiq/model_expansions/quantum_operations/control.py +11 -12
- classiq/model_expansions/quantum_operations/emitter.py +22 -0
- classiq/model_expansions/quantum_operations/expression_operation.py +2 -20
- classiq/model_expansions/quantum_operations/inplace_binary_operation.py +42 -12
- classiq/model_expansions/quantum_operations/invert.py +1 -1
- classiq/model_expansions/quantum_operations/phase.py +4 -5
- classiq/model_expansions/quantum_operations/power.py +1 -1
- classiq/model_expansions/quantum_operations/quantum_assignment_operation.py +50 -9
- classiq/model_expansions/quantum_operations/variable_decleration.py +2 -2
- classiq/model_expansions/quantum_operations/within_apply.py +1 -1
- classiq/qmod/__init__.py +2 -0
- classiq/qmod/builtins/__init__.py +1 -3
- classiq/qmod/builtins/functions/__init__.py +9 -0
- classiq/qmod/builtins/functions/arithmetic.py +10 -0
- classiq/qmod/builtins/functions/standard_gates.py +14 -14
- classiq/qmod/builtins/functions/variational.py +37 -0
- classiq/qmod/create_model_function.py +16 -6
- classiq/qmod/qmod_parameter.py +3 -1
- classiq/qmod/quantum_expandable.py +43 -10
- classiq/qmod/quantum_function.py +24 -2
- classiq/qmod/semantics/static_semantics_visitor.py +3 -1
- classiq/qmod/synthesize_separately.py +16 -0
- classiq/qmod/type_attribute_remover.py +1 -1
- classiq/qmod/write_qmod.py +2 -4
- classiq/synthesis.py +11 -13
- {classiq-0.51.1.dist-info → classiq-0.53.0.dist-info}/METADATA +3 -2
- {classiq-0.51.1.dist-info → classiq-0.53.0.dist-info}/RECORD +158 -152
- {classiq-0.51.1.dist-info → classiq-0.53.0.dist-info}/WHEEL +0 -0
@@ -405,7 +405,7 @@ def RZZ(theta: CReal, target: QArray[QBit, Literal[2]]) -> None:
|
|
405
405
|
|
406
406
|
|
407
407
|
@qfunc(external=True)
|
408
|
-
def CH(
|
408
|
+
def CH(ctrl: QBit, target: QBit) -> None:
|
409
409
|
"""
|
410
410
|
[Qmod core-library function]
|
411
411
|
|
@@ -423,7 +423,7 @@ def CH(control: QBit, target: QBit) -> None:
|
|
423
423
|
$$
|
424
424
|
|
425
425
|
Args:
|
426
|
-
|
426
|
+
ctrl: The control qubit.
|
427
427
|
target: The qubit to apply the Hadamard gate on.
|
428
428
|
|
429
429
|
Link: [Reference Manual](https://docs.classiq.io/latest/reference-manual/qmod/library-reference/core-library-functions/standard_gates/standard_gates/)
|
@@ -432,7 +432,7 @@ def CH(control: QBit, target: QBit) -> None:
|
|
432
432
|
|
433
433
|
|
434
434
|
@qfunc(external=True)
|
435
|
-
def CX(
|
435
|
+
def CX(ctrl: QBit, target: QBit) -> None:
|
436
436
|
"""
|
437
437
|
[Qmod core-library function]
|
438
438
|
|
@@ -450,7 +450,7 @@ def CX(control: QBit, target: QBit) -> None:
|
|
450
450
|
$$
|
451
451
|
|
452
452
|
Args:
|
453
|
-
|
453
|
+
ctrl: The control qubit.
|
454
454
|
target: The qubit to apply the Pauli-X gate on.
|
455
455
|
|
456
456
|
Link: [Reference Manual](https://docs.classiq.io/latest/reference-manual/qmod/library-reference/core-library-functions/standard_gates/standard_gates/)
|
@@ -459,7 +459,7 @@ def CX(control: QBit, target: QBit) -> None:
|
|
459
459
|
|
460
460
|
|
461
461
|
@qfunc(external=True)
|
462
|
-
def CY(
|
462
|
+
def CY(ctrl: QBit, target: QBit) -> None:
|
463
463
|
"""
|
464
464
|
[Qmod core-library function]
|
465
465
|
|
@@ -477,7 +477,7 @@ def CY(control: QBit, target: QBit) -> None:
|
|
477
477
|
$$
|
478
478
|
|
479
479
|
Args:
|
480
|
-
|
480
|
+
ctrl: The control qubit.
|
481
481
|
target: The qubit to apply the Pauli-Y gate on.
|
482
482
|
|
483
483
|
Link: [Reference Manual](https://docs.classiq.io/latest/reference-manual/qmod/library-reference/core-library-functions/standard_gates/standard_gates/)
|
@@ -486,7 +486,7 @@ def CY(control: QBit, target: QBit) -> None:
|
|
486
486
|
|
487
487
|
|
488
488
|
@qfunc(external=True)
|
489
|
-
def CZ(
|
489
|
+
def CZ(ctrl: QBit, target: QBit) -> None:
|
490
490
|
"""
|
491
491
|
[Qmod core-library function]
|
492
492
|
|
@@ -504,7 +504,7 @@ def CZ(control: QBit, target: QBit) -> None:
|
|
504
504
|
$$
|
505
505
|
|
506
506
|
Args:
|
507
|
-
|
507
|
+
ctrl: The control qubit.
|
508
508
|
target: The qubit to apply the Pauli-Z gate on.
|
509
509
|
|
510
510
|
Link: [Reference Manual](https://docs.classiq.io/latest/reference-manual/qmod/library-reference/core-library-functions/standard_gates/standard_gates/)
|
@@ -513,7 +513,7 @@ def CZ(control: QBit, target: QBit) -> None:
|
|
513
513
|
|
514
514
|
|
515
515
|
@qfunc(external=True)
|
516
|
-
def CRX(theta: CReal,
|
516
|
+
def CRX(theta: CReal, ctrl: QBit, target: QBit) -> None:
|
517
517
|
"""
|
518
518
|
[Qmod core-library function]
|
519
519
|
|
@@ -532,7 +532,7 @@ def CRX(theta: CReal, control: QBit, target: QBit) -> None:
|
|
532
532
|
|
533
533
|
Args:
|
534
534
|
theta: The rotation angle in radians.
|
535
|
-
|
535
|
+
ctrl: The control qubit.
|
536
536
|
target: The qubit to apply the RX gate on.
|
537
537
|
|
538
538
|
Link: [Reference Manual](https://docs.classiq.io/latest/reference-manual/qmod/library-reference/core-library-functions/standard_gates/standard_gates/)
|
@@ -541,7 +541,7 @@ def CRX(theta: CReal, control: QBit, target: QBit) -> None:
|
|
541
541
|
|
542
542
|
|
543
543
|
@qfunc(external=True)
|
544
|
-
def CRY(theta: CReal,
|
544
|
+
def CRY(theta: CReal, ctrl: QBit, target: QBit) -> None:
|
545
545
|
"""
|
546
546
|
[Qmod core-library function]
|
547
547
|
|
@@ -569,7 +569,7 @@ def CRY(theta: CReal, control: QBit, target: QBit) -> None:
|
|
569
569
|
|
570
570
|
|
571
571
|
@qfunc(external=True)
|
572
|
-
def CRZ(theta: CReal,
|
572
|
+
def CRZ(theta: CReal, ctrl: QBit, target: QBit) -> None:
|
573
573
|
"""
|
574
574
|
[Qmod core-library function]
|
575
575
|
|
@@ -597,7 +597,7 @@ def CRZ(theta: CReal, control: QBit, target: QBit) -> None:
|
|
597
597
|
|
598
598
|
|
599
599
|
@qfunc(external=True)
|
600
|
-
def CPHASE(theta: CReal,
|
600
|
+
def CPHASE(theta: CReal, ctrl: QBit, target: QBit) -> None:
|
601
601
|
"""
|
602
602
|
[Qmod core-library function]
|
603
603
|
|
@@ -707,7 +707,7 @@ def U(theta: CReal, phi: CReal, lam: CReal, gam: CReal, target: QBit) -> None:
|
|
707
707
|
|
708
708
|
|
709
709
|
@qfunc(external=True)
|
710
|
-
def CCX(
|
710
|
+
def CCX(ctrl: QArray[QBit, Literal[2]], target: QBit) -> None:
|
711
711
|
"""
|
712
712
|
[Qmod core-library function]
|
713
713
|
|
@@ -0,0 +1,37 @@
|
|
1
|
+
from classiq.qmod.cparam import CReal
|
2
|
+
from classiq.qmod.qfunc import qfunc
|
3
|
+
from classiq.qmod.qmod_parameter import CArray
|
4
|
+
from classiq.qmod.qmod_variable import Output, QArray, QBit
|
5
|
+
|
6
|
+
|
7
|
+
@qfunc(external=True)
|
8
|
+
def encode_in_angle(data: CArray[CReal], qba: Output[QArray[QBit]]) -> None:
|
9
|
+
"""
|
10
|
+
[Qmod Classiq-library function]
|
11
|
+
|
12
|
+
Creates an angle encoding of n data points on n qubits.
|
13
|
+
|
14
|
+
Applies RY($\\pi$data[i]) on qba[i].
|
15
|
+
|
16
|
+
Args:
|
17
|
+
data: A classical array representing the data to encode.
|
18
|
+
qba: The array of qubits on which the data is encoded.
|
19
|
+
"""
|
20
|
+
pass
|
21
|
+
|
22
|
+
|
23
|
+
@qfunc(external=True)
|
24
|
+
def encode_on_bloch(data: CArray[CReal], qba: Output[QArray]) -> None:
|
25
|
+
"""
|
26
|
+
[Qmod Classiq-library function]
|
27
|
+
|
28
|
+
Creates a dense angle encoding of n data points on n//2 qubits.
|
29
|
+
|
30
|
+
Encodes pairs of data points on a Bloch sphere, via RX($\\pi$data[2*i])RZ($\\pi$data[2*i+1]) on qba[i].
|
31
|
+
If the length of the data is odd then RX($\\pi$data[i]) is applied on the last qubit.
|
32
|
+
|
33
|
+
Args:
|
34
|
+
data: A classical array representing the data to encode.
|
35
|
+
qba: The QArray of QBits on which the data is encoded.
|
36
|
+
"""
|
37
|
+
pass
|
@@ -155,9 +155,9 @@ def _get_wrapper_main(gen_main: QFunc, preferences: Optional[Preferences]) -> Mo
|
|
155
155
|
|
156
156
|
|
157
157
|
def _get_all_model_functions_as_generative_functions() -> List[GenerativeQFunc]:
|
158
|
+
|
158
159
|
gen_functions = list(GEN_QFUNCS) + [
|
159
|
-
|
160
|
-
for dec_func in DEC_QFUNCS
|
160
|
+
_get_gen_from_dec(dec_func) for dec_func in DEC_QFUNCS
|
161
161
|
]
|
162
162
|
return [
|
163
163
|
(
|
@@ -165,7 +165,7 @@ def _get_all_model_functions_as_generative_functions() -> List[GenerativeQFunc]:
|
|
165
165
|
if gen_func.func_decl.name != MAIN_FUNCTION_NAME
|
166
166
|
else GenerativeQFunc(
|
167
167
|
gen_func._py_callable,
|
168
|
-
gen_func.func_decl.
|
168
|
+
gen_func.func_decl.model_copy(update={"name": GEN_MAIN_NAME}),
|
169
169
|
)
|
170
170
|
)
|
171
171
|
for gen_func in gen_functions
|
@@ -173,6 +173,16 @@ def _get_all_model_functions_as_generative_functions() -> List[GenerativeQFunc]:
|
|
173
173
|
]
|
174
174
|
|
175
175
|
|
176
|
+
def _get_gen_from_dec(dec_func: QFunc) -> GenerativeQFunc:
|
177
|
+
synthesis_data = dec_func.synthesis_data
|
178
|
+
if synthesis_data is not None and synthesis_data.should_synthesize_separately:
|
179
|
+
raise ClassiqError(
|
180
|
+
"""The model contains generative functions,
|
181
|
+
which cannot coexist with functions marked for separate synthesis"""
|
182
|
+
)
|
183
|
+
return GenerativeQFunc(dec_func._py_callable, dec_func.func_decl)
|
184
|
+
|
185
|
+
|
176
186
|
def _interpret_generative_model(
|
177
187
|
gen_model: Model, gen_functions: List[GenerativeQFunc]
|
178
188
|
) -> Dict[str, NativeFunctionDefinition]:
|
@@ -188,9 +198,9 @@ def _interpret_generative_model(
|
|
188
198
|
expanded_gen_main_name = cast(
|
189
199
|
QuantumFunctionCall, functions_dict[MAIN_FUNCTION_NAME].body[0]
|
190
200
|
).func_name
|
191
|
-
functions_dict[MAIN_FUNCTION_NAME] = functions_dict[
|
192
|
-
|
193
|
-
)
|
201
|
+
functions_dict[MAIN_FUNCTION_NAME] = functions_dict[
|
202
|
+
expanded_gen_main_name
|
203
|
+
].model_copy(update={"name": MAIN_FUNCTION_NAME})
|
194
204
|
functions_dict.pop(expanded_gen_main_name)
|
195
205
|
|
196
206
|
return functions_dict
|
classiq/qmod/qmod_parameter.py
CHANGED
@@ -44,7 +44,9 @@ class CParamList(CParam):
|
|
44
44
|
self._list_type = list_type
|
45
45
|
|
46
46
|
def __getitem__(self, key: Any) -> CParam:
|
47
|
+
param_type = self._list_type.element_type
|
47
48
|
if isinstance(key, slice):
|
49
|
+
param_type = self._list_type
|
48
50
|
start = key.start if key.start is not None else ""
|
49
51
|
stop = key.stop if key.stop is not None else ""
|
50
52
|
if key.step is not None:
|
@@ -53,7 +55,7 @@ class CParamList(CParam):
|
|
53
55
|
key = f"{start}:{stop}"
|
54
56
|
return create_param(
|
55
57
|
f"({self})[{key}]",
|
56
|
-
|
58
|
+
param_type,
|
57
59
|
qmodule=self._qmodule,
|
58
60
|
)
|
59
61
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import inspect
|
2
|
+
import warnings
|
2
3
|
from abc import ABC
|
3
4
|
from dataclasses import is_dataclass
|
4
5
|
from enum import Enum as PythonEnum
|
@@ -17,12 +18,16 @@ from typing import (
|
|
17
18
|
overload,
|
18
19
|
)
|
19
20
|
|
21
|
+
import pydantic
|
20
22
|
from sympy import Basic
|
21
23
|
from typing_extensions import Self
|
22
24
|
|
23
|
-
from classiq.interface.exceptions import ClassiqValueError
|
25
|
+
from classiq.interface.exceptions import ClassiqDeprecationWarning, ClassiqValueError
|
24
26
|
from classiq.interface.generator.expressions.expression import Expression
|
25
|
-
from classiq.interface.generator.functions.concrete_types import
|
27
|
+
from classiq.interface.generator.functions.concrete_types import (
|
28
|
+
NativePythonClassicalTypes,
|
29
|
+
PythonClassicalPydanticTypes,
|
30
|
+
)
|
26
31
|
from classiq.interface.model.classical_parameter_declaration import (
|
27
32
|
AnonClassicalParameterDeclaration,
|
28
33
|
)
|
@@ -334,15 +339,24 @@ def prepare_arg(
|
|
334
339
|
def _validate_classical_arg(
|
335
340
|
arg: Any, arg_decl: AnonClassicalParameterDeclaration, func_name: Optional[str]
|
336
341
|
) -> None:
|
342
|
+
is_native_or_compatible_type = not isinstance(
|
343
|
+
arg, (*NativePythonClassicalTypes, CParam, SymbolicExpr, Basic, PythonEnum)
|
344
|
+
) and not is_dataclass(
|
345
|
+
arg
|
346
|
+
) # type: ignore[unreachable]
|
347
|
+
try:
|
348
|
+
is_pydantic_classical_type = isinstance(
|
349
|
+
arg, pydantic.BaseModel
|
350
|
+
) and not isinstance(arg, PythonClassicalPydanticTypes)
|
351
|
+
except ClassiqValueError:
|
352
|
+
is_pydantic_classical_type = False
|
353
|
+
|
354
|
+
is_incompatible_symbolic_expr = isinstance(arg, SymbolicExpr) and arg.is_quantum
|
355
|
+
|
337
356
|
if (
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
and not is_dataclass(arg) # type:ignore[unreachable]
|
342
|
-
or isinstance(arg, SymbolicExpr)
|
343
|
-
and arg.is_quantum
|
344
|
-
):
|
345
|
-
func_name_message = "" if func_name is None else f" of function {func_name!r}"
|
357
|
+
is_native_or_compatible_type or is_pydantic_classical_type
|
358
|
+
) or is_incompatible_symbolic_expr:
|
359
|
+
func_name_message = f" of function {func_name!r}" if func_name else ""
|
346
360
|
raise ClassiqValueError(
|
347
361
|
f"Argument {str(arg)!r} to parameter {arg_decl.name!r}{func_name_message} "
|
348
362
|
f"has incompatible type; expected "
|
@@ -379,6 +393,7 @@ def _get_operand_hint(
|
|
379
393
|
def _prepare_args(
|
380
394
|
decl: AnonQuantumFunctionDeclaration, arg_list: List[Any], kwargs: Dict[str, Any]
|
381
395
|
) -> List[ArgValue]:
|
396
|
+
_apply_control_backward_compatibility(decl, kwargs)
|
382
397
|
result = []
|
383
398
|
for idx, arg_decl in enumerate(decl.positional_arg_declarations):
|
384
399
|
arg = None
|
@@ -401,6 +416,24 @@ def _prepare_args(
|
|
401
416
|
return result
|
402
417
|
|
403
418
|
|
419
|
+
def _apply_control_backward_compatibility(
|
420
|
+
decl: AnonQuantumFunctionDeclaration, kwargs: Dict[str, Any]
|
421
|
+
) -> None:
|
422
|
+
from classiq.qmod.builtins.functions import __all__ as builtin_functions
|
423
|
+
|
424
|
+
if decl.name in builtin_functions and "control" in kwargs:
|
425
|
+
warnings.warn(
|
426
|
+
f"Parameter 'control' of function {decl.name!r} has been renamed to "
|
427
|
+
f"'ctrl'. Parameter 'control' will no longer be supported starting on "
|
428
|
+
f"4/11/24 at the earliest.\nHint: Change {decl.name}(control=...) to "
|
429
|
+
f"{decl.name}(ctrl=...).",
|
430
|
+
ClassiqDeprecationWarning,
|
431
|
+
stacklevel=6,
|
432
|
+
)
|
433
|
+
kwargs["ctrl"] = kwargs["control"]
|
434
|
+
kwargs.pop("control")
|
435
|
+
|
436
|
+
|
404
437
|
def _create_quantum_function_call(
|
405
438
|
decl_: QuantumFunctionDeclaration,
|
406
439
|
index_: Optional[Union[CParamScalar, int]] = None,
|
classiq/qmod/quantum_function.py
CHANGED
@@ -10,7 +10,10 @@ from classiq.interface.executor.execution_preferences import ExecutionPreference
|
|
10
10
|
from classiq.interface.generator.model.constraints import Constraints
|
11
11
|
from classiq.interface.generator.model.preferences.preferences import Preferences
|
12
12
|
from classiq.interface.model.model import Model
|
13
|
-
from classiq.interface.model.native_function_definition import
|
13
|
+
from classiq.interface.model.native_function_definition import (
|
14
|
+
FunctionSynthesisData,
|
15
|
+
NativeFunctionDefinition,
|
16
|
+
)
|
14
17
|
from classiq.interface.model.quantum_function_declaration import (
|
15
18
|
NamedParamsQuantumFunctionDeclaration,
|
16
19
|
)
|
@@ -32,6 +35,7 @@ class QFunc(QExpandable):
|
|
32
35
|
_validate_no_gen_params(py_callable.__annotations__)
|
33
36
|
super().__init__(py_callable)
|
34
37
|
functools.update_wrapper(self, py_callable)
|
38
|
+
self._synthesis_data: Optional[FunctionSynthesisData] = None
|
35
39
|
|
36
40
|
@property
|
37
41
|
def func_decl(self) -> NamedParamsQuantumFunctionDeclaration:
|
@@ -40,6 +44,14 @@ class QFunc(QExpandable):
|
|
40
44
|
infer_func_decl(self._py_callable, qmodule=self._qmodule),
|
41
45
|
)
|
42
46
|
|
47
|
+
@property
|
48
|
+
def synthesis_data(self) -> Optional[FunctionSynthesisData]:
|
49
|
+
return self._synthesis_data
|
50
|
+
|
51
|
+
@synthesis_data.setter
|
52
|
+
def synthesis_data(self, value: FunctionSynthesisData) -> None:
|
53
|
+
self._synthesis_data = value
|
54
|
+
|
43
55
|
def __call__(self, *args: Any, **kwargs: Any) -> None:
|
44
56
|
super().__call__(*args, **kwargs)
|
45
57
|
self.expand()
|
@@ -82,7 +94,17 @@ class QFunc(QExpandable):
|
|
82
94
|
return
|
83
95
|
super().expand()
|
84
96
|
self._qmodule.native_defs[self.func_decl.name] = NativeFunctionDefinition(
|
85
|
-
**{
|
97
|
+
**{
|
98
|
+
**self.func_decl.model_dump(),
|
99
|
+
**{
|
100
|
+
"body": self.body,
|
101
|
+
"synthesis_data": (
|
102
|
+
self.synthesis_data
|
103
|
+
if self.synthesis_data is not None
|
104
|
+
else FunctionSynthesisData()
|
105
|
+
),
|
106
|
+
},
|
107
|
+
},
|
86
108
|
)
|
87
109
|
|
88
110
|
def _add_constants_from_classical_code(
|
@@ -209,7 +209,9 @@ class StaticSemanticsVisitor(Visitor):
|
|
209
209
|
**self.current_scope.operands,
|
210
210
|
},
|
211
211
|
)
|
212
|
-
elif isinstance(op, InplaceBinaryOperation)
|
212
|
+
elif isinstance(op, InplaceBinaryOperation) and isinstance(
|
213
|
+
op.value, HandleBinding
|
214
|
+
):
|
213
215
|
check_no_overlapping_quantum_args(
|
214
216
|
[op.target, op.value], op.operation.value
|
215
217
|
)
|
@@ -0,0 +1,16 @@
|
|
1
|
+
from typing import Union
|
2
|
+
|
3
|
+
from classiq.interface.exceptions import ClassiqError
|
4
|
+
from classiq.interface.model.native_function_definition import FunctionSynthesisData
|
5
|
+
|
6
|
+
from classiq.qmod.quantum_function import ExternalQFunc, GenerativeQFunc, QFunc
|
7
|
+
|
8
|
+
|
9
|
+
def synthesize_separately(qfunc: Union[QFunc, GenerativeQFunc, ExternalQFunc]) -> QFunc:
|
10
|
+
if isinstance(qfunc, QFunc):
|
11
|
+
qfunc.synthesis_data = FunctionSynthesisData(should_synthesize_separately=True)
|
12
|
+
return qfunc
|
13
|
+
if isinstance(qfunc, GenerativeQFunc):
|
14
|
+
raise ClassiqError("Generative functions can not be synthesized separately")
|
15
|
+
if isinstance(qfunc, ExternalQFunc):
|
16
|
+
raise ClassiqError("External functions can not be synthesized separately")
|
@@ -10,7 +10,7 @@ def decl_without_type_attributes(
|
|
10
10
|
operand_declaration: AnonQuantumOperandDeclaration,
|
11
11
|
) -> AnonQuantumOperandDeclaration:
|
12
12
|
remover = AttributeRemover()
|
13
|
-
return operand_declaration.
|
13
|
+
return operand_declaration.model_copy(
|
14
14
|
update=dict(
|
15
15
|
positional_arg_declarations=[
|
16
16
|
remover.visit(arg) if isinstance(arg, PortDeclaration) else arg
|
classiq/qmod/write_qmod.py
CHANGED
@@ -31,14 +31,12 @@ def write_qmod(
|
|
31
31
|
None
|
32
32
|
"""
|
33
33
|
|
34
|
-
model = Model.
|
34
|
+
model = Model.model_validate_json(serialized_model)
|
35
35
|
pretty_printed_model = DSLPrettyPrinter(decimal_precision=decimal_precision).visit(
|
36
36
|
model
|
37
37
|
)
|
38
38
|
|
39
|
-
synthesis_options = model.
|
40
|
-
include={"constraints", "preferences"}, exclude_unset=True
|
41
|
-
)
|
39
|
+
synthesis_options = model.model_dump(include={"constraints", "preferences"})
|
42
40
|
|
43
41
|
synthesis_options_path = Path(f"{name}.{_SYNTHESIS_OPTIONS_SUFFIX}")
|
44
42
|
if directory is not None:
|
classiq/synthesis.py
CHANGED
@@ -32,8 +32,8 @@ def show(quantum_program: SerializedQuantumProgram) -> None:
|
|
32
32
|
[Visualization tool](https://docs.classiq.io/latest/reference-manual/analyzer/quantum-program-visualization-tool/)
|
33
33
|
"""
|
34
34
|
try:
|
35
|
-
circuit = QuantumProgram.
|
36
|
-
except pydantic.
|
35
|
+
circuit = QuantumProgram.model_validate_json(quantum_program)
|
36
|
+
except pydantic.ValidationError as exc:
|
37
37
|
raise ClassiqValueError(CANT_PARSE_QUANTUM_PROGRAM_MSG) from exc
|
38
38
|
circuit.show() # type: ignore[attr-defined]
|
39
39
|
|
@@ -42,7 +42,7 @@ async def quantum_program_from_qasm_async(qasm: str) -> SerializedQuantumProgram
|
|
42
42
|
quantum_program = await ApiWrapper.get_generated_circuit_from_qasm(
|
43
43
|
QasmCode(code=qasm)
|
44
44
|
)
|
45
|
-
return SerializedQuantumProgram(quantum_program.
|
45
|
+
return SerializedQuantumProgram(quantum_program.model_dump_json())
|
46
46
|
|
47
47
|
|
48
48
|
def quantum_program_from_qasm(qasm: str) -> SerializedQuantumProgram:
|
@@ -61,9 +61,9 @@ def quantum_program_from_qasm(qasm: str) -> SerializedQuantumProgram:
|
|
61
61
|
async def synthesize_async(
|
62
62
|
serialized_model: SerializedModel,
|
63
63
|
) -> SerializedQuantumProgram:
|
64
|
-
model =
|
64
|
+
model = Model.model_validate_json(serialized_model)
|
65
65
|
quantum_program = await ApiWrapper.call_generation_task(model)
|
66
|
-
return SerializedQuantumProgram(quantum_program.
|
66
|
+
return SerializedQuantumProgram(quantum_program.model_dump_json(indent=2))
|
67
67
|
|
68
68
|
|
69
69
|
def synthesize(
|
@@ -109,7 +109,7 @@ def set_preferences(
|
|
109
109
|
"Missing preferences. Either pass `Preferences` object or pass keywords"
|
110
110
|
)
|
111
111
|
|
112
|
-
model =
|
112
|
+
model = Model.model_validate_json(serialized_model)
|
113
113
|
model.preferences = preferences
|
114
114
|
return model.get_model()
|
115
115
|
|
@@ -127,11 +127,10 @@ def update_preferences(
|
|
127
127
|
Returns:
|
128
128
|
SerializedModel: The updated model with the new preferences applied.
|
129
129
|
"""
|
130
|
-
model =
|
130
|
+
model = Model.model_validate_json(serialized_model)
|
131
131
|
|
132
132
|
for key, value in kwargs.items():
|
133
133
|
setattr(model.preferences, key, value)
|
134
|
-
|
135
134
|
return model.get_model()
|
136
135
|
|
137
136
|
|
@@ -158,7 +157,7 @@ def set_constraints(
|
|
158
157
|
"Missing constraints. Either pass `Constraints` object or pass keywords"
|
159
158
|
)
|
160
159
|
|
161
|
-
model =
|
160
|
+
model = Model.model_validate_json(serialized_model)
|
162
161
|
model.constraints = constraints
|
163
162
|
return model.get_model()
|
164
163
|
|
@@ -176,11 +175,10 @@ def update_constraints(
|
|
176
175
|
Returns:
|
177
176
|
SerializedModel: The updated model with the new constraints applied.
|
178
177
|
"""
|
179
|
-
model =
|
178
|
+
model = Model.model_validate_json(serialized_model)
|
180
179
|
|
181
180
|
for key, value in kwargs.items():
|
182
181
|
setattr(model.constraints, key, value)
|
183
|
-
|
184
182
|
return model.get_model()
|
185
183
|
|
186
184
|
|
@@ -208,7 +206,7 @@ def set_execution_preferences(
|
|
208
206
|
"Missing execution_preferences. Either pass `ExecutionPreferences` object or pass keywords"
|
209
207
|
)
|
210
208
|
|
211
|
-
model =
|
209
|
+
model = Model.model_validate_json(serialized_model)
|
212
210
|
model.execution_preferences = execution_preferences
|
213
211
|
return model.get_model()
|
214
212
|
|
@@ -226,7 +224,7 @@ def update_execution_preferences(
|
|
226
224
|
Returns:
|
227
225
|
SerializedModel: The updated model with the new execution_preferences applied.
|
228
226
|
"""
|
229
|
-
model =
|
227
|
+
model = Model.model_validate_json(serialized_model)
|
230
228
|
|
231
229
|
for key, value in kwargs.items():
|
232
230
|
setattr(model.execution_preferences, key, value)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: classiq
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.53.0
|
4
4
|
Summary: Classiq's Python SDK for quantum computing
|
5
5
|
Home-page: https://classiq.io
|
6
6
|
License: Proprietary
|
@@ -46,7 +46,8 @@ Requires-Dist: numpy (>=1.26.0,<2.0.0) ; python_version >= "3.12"
|
|
46
46
|
Requires-Dist: packaging (>=23.2,<24.0)
|
47
47
|
Requires-Dist: pandas (>=1.4.0,<3.0.0)
|
48
48
|
Requires-Dist: plotly (>=5.7.0,<6.0.0)
|
49
|
-
Requires-Dist: pydantic (>=
|
49
|
+
Requires-Dist: pydantic (>=2.9.0,<3.0.0)
|
50
|
+
Requires-Dist: pydantic-settings (>=2.4.0,<3.0.0)
|
50
51
|
Requires-Dist: scipy (>=1.10.0,<2.0.0) ; python_version < "3.12"
|
51
52
|
Requires-Dist: scipy (>=1.11.0,<2.0.0) ; python_version >= "3.12"
|
52
53
|
Requires-Dist: sympy (>=1.13.0,<2.0.0)
|