classiq 0.37.0__py3-none-any.whl → 0.38.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- classiq/__init__.py +2 -2
- classiq/_analyzer_extras/_ipywidgets_async_extension.py +1 -1
- classiq/_analyzer_extras/interactive_hardware.py +3 -3
- classiq/_internals/api_wrapper.py +24 -16
- classiq/_internals/async_utils.py +1 -74
- classiq/_internals/authentication/device.py +9 -4
- classiq/_internals/authentication/password_manager.py +25 -10
- classiq/_internals/authentication/token_manager.py +2 -2
- classiq/_internals/client.py +13 -5
- classiq/_internals/jobs.py +10 -7
- classiq/analyzer/analyzer.py +26 -28
- classiq/analyzer/analyzer_utilities.py +5 -5
- classiq/analyzer/rb.py +4 -5
- classiq/analyzer/show_interactive_hack.py +6 -6
- classiq/applications/benchmarking/mirror_benchmarking.py +9 -6
- classiq/applications/combinatorial_optimization/__init__.py +5 -0
- classiq/applications/qnn/circuit_utils.py +2 -2
- classiq/applications/qnn/gradients/quantum_gradient.py +2 -2
- classiq/applications/qnn/types.py +2 -2
- classiq/applications/qsvm/qsvm.py +4 -7
- classiq/applications/qsvm/qsvm_data_generation.py +2 -5
- classiq/applications_model_constructors/__init__.py +9 -1
- classiq/applications_model_constructors/chemistry_model_constructor.py +9 -16
- classiq/applications_model_constructors/combinatorial_helpers/__init__.py +0 -0
- classiq/applications_model_constructors/combinatorial_helpers/allowed_constraints.py +20 -0
- classiq/applications_model_constructors/combinatorial_helpers/arithmetic/__init__.py +0 -0
- classiq/applications_model_constructors/combinatorial_helpers/arithmetic/arithmetic_expression.py +35 -0
- classiq/applications_model_constructors/combinatorial_helpers/arithmetic/isolation.py +42 -0
- classiq/applications_model_constructors/combinatorial_helpers/combinatorial_problem_utils.py +130 -0
- classiq/applications_model_constructors/combinatorial_helpers/encoding_mapping.py +107 -0
- classiq/applications_model_constructors/combinatorial_helpers/encoding_utils.py +122 -0
- classiq/applications_model_constructors/combinatorial_helpers/memory.py +79 -0
- classiq/applications_model_constructors/combinatorial_helpers/multiple_comp_basis_sp.py +34 -0
- classiq/applications_model_constructors/combinatorial_helpers/optimization_model.py +166 -0
- classiq/applications_model_constructors/combinatorial_helpers/pauli_helpers/__init__.py +0 -0
- classiq/applications_model_constructors/combinatorial_helpers/pauli_helpers/pauli_sparsing.py +31 -0
- classiq/applications_model_constructors/combinatorial_helpers/pauli_helpers/pauli_utils.py +65 -0
- classiq/applications_model_constructors/combinatorial_helpers/py.typed +0 -0
- classiq/applications_model_constructors/combinatorial_helpers/pyomo_utils.py +243 -0
- classiq/applications_model_constructors/combinatorial_helpers/sympy_utils.py +22 -0
- classiq/applications_model_constructors/combinatorial_helpers/transformations/__init__.py +0 -0
- classiq/applications_model_constructors/combinatorial_helpers/transformations/encoding.py +194 -0
- classiq/applications_model_constructors/combinatorial_helpers/transformations/fixed_variables.py +144 -0
- classiq/applications_model_constructors/combinatorial_helpers/transformations/ising_converter.py +124 -0
- classiq/applications_model_constructors/combinatorial_helpers/transformations/penalty.py +32 -0
- classiq/applications_model_constructors/combinatorial_helpers/transformations/penalty_support.py +41 -0
- classiq/applications_model_constructors/combinatorial_helpers/transformations/sign_seperation.py +75 -0
- classiq/applications_model_constructors/combinatorial_helpers/transformations/slack_variables.py +90 -0
- classiq/applications_model_constructors/combinatorial_optimization_model_constructor.py +48 -91
- classiq/applications_model_constructors/finance_model_constructor.py +4 -17
- classiq/applications_model_constructors/grover_model_constructor.py +20 -91
- classiq/applications_model_constructors/libraries/qmci_library.py +17 -19
- classiq/builtin_functions/standard_gates.py +1 -1
- classiq/exceptions.py +43 -1
- classiq/executor.py +10 -9
- classiq/interface/_version.py +1 -1
- classiq/interface/analyzer/analysis_params.py +6 -3
- classiq/interface/analyzer/result.py +12 -4
- classiq/interface/applications/qsvm.py +13 -1
- classiq/interface/backend/backend_preferences.py +4 -2
- classiq/interface/backend/pydantic_backend.py +3 -1
- classiq/interface/backend/quantum_backend_providers.py +1 -0
- classiq/interface/chemistry/fermionic_operator.py +15 -13
- classiq/interface/chemistry/ground_state_problem.py +18 -3
- classiq/interface/chemistry/molecule.py +8 -6
- classiq/interface/chemistry/operator.py +20 -14
- classiq/interface/combinatorial_optimization/examples/ascending_sequence.py +1 -1
- classiq/interface/combinatorial_optimization/examples/greater_than_ilp.py +1 -1
- classiq/interface/combinatorial_optimization/examples/ilp.py +2 -1
- classiq/interface/combinatorial_optimization/examples/integer_portfolio_optimization.py +2 -2
- classiq/interface/combinatorial_optimization/examples/mds.py +2 -1
- classiq/interface/combinatorial_optimization/examples/mht.py +3 -3
- classiq/interface/combinatorial_optimization/examples/mis.py +4 -1
- classiq/interface/combinatorial_optimization/examples/mvc.py +2 -1
- classiq/interface/combinatorial_optimization/examples/set_cover.py +2 -1
- classiq/interface/combinatorial_optimization/examples/tsp.py +4 -3
- classiq/interface/combinatorial_optimization/examples/tsp_digraph.py +6 -2
- classiq/interface/combinatorial_optimization/mht_qaoa_input.py +9 -3
- classiq/interface/executor/aws_execution_cost.py +4 -3
- classiq/interface/executor/estimation.py +2 -2
- classiq/interface/executor/execution_preferences.py +5 -34
- classiq/interface/executor/execution_request.py +19 -17
- classiq/interface/executor/optimizer_preferences.py +22 -13
- classiq/interface/executor/{quantum_program.py → quantum_code.py} +21 -15
- classiq/interface/executor/quantum_instruction_set.py +2 -1
- classiq/interface/executor/register_initialization.py +1 -3
- classiq/interface/executor/result.py +41 -10
- classiq/interface/executor/vqe_result.py +1 -1
- classiq/interface/finance/function_input.py +17 -4
- classiq/interface/finance/gaussian_model_input.py +3 -1
- classiq/interface/finance/log_normal_model_input.py +3 -1
- classiq/interface/finance/model_input.py +2 -0
- classiq/interface/generator/amplitude_loading.py +6 -3
- classiq/interface/generator/application_apis/__init__.py +1 -0
- classiq/interface/generator/application_apis/arithmetic_declarations.py +14 -0
- classiq/interface/generator/arith/argument_utils.py +14 -4
- classiq/interface/generator/arith/arithmetic.py +3 -1
- classiq/interface/generator/arith/arithmetic_arg_type_validator.py +12 -13
- classiq/interface/generator/arith/arithmetic_expression_abc.py +4 -1
- classiq/interface/generator/arith/arithmetic_expression_parser.py +8 -2
- classiq/interface/generator/arith/arithmetic_expression_validator.py +16 -2
- classiq/interface/generator/arith/arithmetic_operations.py +5 -10
- classiq/interface/generator/arith/ast_node_rewrite.py +1 -1
- classiq/interface/generator/arith/binary_ops.py +202 -54
- classiq/interface/generator/arith/extremum_operations.py +5 -3
- classiq/interface/generator/arith/logical_ops.py +4 -2
- classiq/interface/generator/arith/machine_precision.py +3 -0
- classiq/interface/generator/arith/number_utils.py +34 -44
- classiq/interface/generator/arith/register_user_input.py +21 -1
- classiq/interface/generator/arith/unary_ops.py +16 -25
- classiq/interface/generator/chemistry_function_params.py +4 -4
- classiq/interface/generator/commuting_pauli_exponentiation.py +3 -1
- classiq/interface/generator/compiler_keywords.py +4 -0
- classiq/interface/generator/complex_type.py +3 -10
- classiq/interface/generator/control_state.py +5 -3
- classiq/interface/generator/credit_risk_example/linear_gci.py +10 -3
- classiq/interface/generator/credit_risk_example/weighted_adder.py +14 -4
- classiq/interface/generator/expressions/atomic_expression_functions.py +5 -3
- classiq/interface/generator/expressions/evaluated_expression.py +18 -4
- classiq/interface/generator/expressions/expression.py +1 -1
- classiq/interface/generator/expressions/qmod_qscalar_proxy.py +33 -0
- classiq/interface/generator/expressions/sympy_supported_expressions.py +2 -1
- classiq/interface/generator/finance.py +1 -1
- classiq/interface/generator/function_params.py +7 -6
- classiq/interface/generator/functions/__init__.py +1 -1
- classiq/interface/generator/functions/core_lib_declarations/quantum_functions/std_lib_functions.py +505 -138
- classiq/interface/generator/functions/core_lib_declarations/quantum_operators.py +25 -99
- classiq/interface/generator/functions/foreign_function_definition.py +12 -4
- classiq/interface/generator/functions/function_implementation.py +8 -4
- classiq/interface/generator/functions/native_function_definition.py +4 -2
- classiq/interface/generator/functions/register.py +4 -2
- classiq/interface/generator/functions/register_mapping_data.py +14 -10
- classiq/interface/generator/generated_circuit_data.py +2 -2
- classiq/interface/generator/grover_operator.py +5 -3
- classiq/interface/generator/hamiltonian_evolution/suzuki_trotter.py +5 -1
- classiq/interface/generator/hardware/hardware_data.py +6 -4
- classiq/interface/generator/hardware_efficient_ansatz.py +25 -8
- classiq/interface/generator/hartree_fock.py +3 -1
- classiq/interface/generator/linear_pauli_rotations.py +3 -1
- classiq/interface/generator/mcu.py +5 -3
- classiq/interface/generator/mcx.py +7 -5
- classiq/interface/generator/model/constraints.py +2 -1
- classiq/interface/generator/model/model.py +11 -19
- classiq/interface/generator/model/preferences/preferences.py +4 -3
- classiq/interface/generator/oracles/custom_oracle.py +4 -2
- classiq/interface/generator/oracles/oracle_abc.py +2 -2
- classiq/interface/generator/qpe.py +6 -4
- classiq/interface/generator/qsvm.py +5 -8
- classiq/interface/generator/quantum_function_call.py +21 -16
- classiq/interface/generator/{generated_circuit.py → quantum_program.py} +10 -14
- classiq/interface/generator/range_types.py +3 -1
- classiq/interface/generator/slice_parsing_utils.py +8 -3
- classiq/interface/generator/standard_gates/controlled_standard_gates.py +4 -2
- classiq/interface/generator/state_preparation/metrics.py +2 -1
- classiq/interface/generator/state_preparation/state_preparation.py +7 -5
- classiq/interface/generator/state_propagator.py +16 -5
- classiq/interface/generator/types/builtin_struct_declarations/__init__.py +0 -1
- classiq/interface/generator/types/struct_declaration.py +8 -3
- classiq/interface/generator/ucc.py +6 -4
- classiq/interface/generator/unitary_gate.py +7 -3
- classiq/interface/generator/validations/flow_graph.py +6 -4
- classiq/interface/generator/validations/validator_functions.py +6 -4
- classiq/interface/hardware.py +2 -2
- classiq/interface/helpers/custom_encoders.py +3 -0
- classiq/interface/helpers/pydantic_model_helpers.py +0 -6
- classiq/interface/helpers/validation_helpers.py +1 -1
- classiq/interface/helpers/versioned_model.py +4 -1
- classiq/interface/ide/show.py +2 -2
- classiq/interface/jobs.py +72 -3
- classiq/interface/model/bind_operation.py +18 -11
- classiq/interface/model/call_synthesis_data.py +68 -0
- classiq/interface/model/inplace_binary_operation.py +2 -2
- classiq/interface/model/model.py +27 -21
- classiq/interface/model/native_function_definition.py +3 -5
- classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +9 -4
- classiq/interface/model/quantum_expressions/control_state.py +2 -2
- classiq/interface/model/quantum_function_call.py +25 -139
- classiq/interface/model/quantum_function_declaration.py +8 -0
- classiq/interface/model/quantum_if_operation.py +2 -3
- classiq/interface/model/quantum_lambda_function.py +64 -0
- classiq/interface/model/quantum_type.py +57 -56
- classiq/interface/model/quantum_variable_declaration.py +1 -1
- classiq/interface/model/statement_block.py +32 -0
- classiq/interface/model/validations/handles_validator.py +14 -12
- classiq/interface/model/within_apply_operation.py +11 -0
- classiq/interface/pyomo_extension/pyomo_sympy_bimap.py +4 -1
- classiq/interface/server/routes.py +5 -0
- classiq/model/function_handler.py +5 -9
- classiq/model/model.py +2 -19
- classiq/qmod/__init__.py +13 -6
- classiq/qmod/builtins/classical_execution_primitives.py +27 -36
- classiq/qmod/builtins/classical_functions.py +24 -14
- classiq/qmod/builtins/functions.py +162 -145
- classiq/qmod/builtins/operations.py +24 -35
- classiq/qmod/builtins/structs.py +15 -15
- classiq/qmod/cfunc.py +42 -0
- classiq/qmod/classical_function.py +6 -14
- classiq/qmod/declaration_inferrer.py +12 -21
- classiq/qmod/expression_query.py +23 -0
- classiq/qmod/model_state_container.py +2 -0
- classiq/qmod/native/__init__.py +0 -0
- classiq/qmod/native/expression_to_qmod.py +189 -0
- classiq/qmod/native/pretty_printer.py +311 -0
- classiq/qmod/qfunc.py +27 -0
- classiq/qmod/qmod_constant.py +76 -0
- classiq/qmod/qmod_parameter.py +34 -12
- classiq/qmod/qmod_struct.py +3 -3
- classiq/qmod/qmod_variable.py +102 -18
- classiq/qmod/quantum_expandable.py +16 -16
- classiq/qmod/quantum_function.py +37 -8
- classiq/qmod/symbolic.py +47 -4
- classiq/qmod/symbolic_expr.py +9 -0
- classiq/qmod/utilities.py +13 -0
- classiq/qmod/write_qmod.py +39 -0
- classiq/quantum_functions/__init__.py +2 -2
- classiq/quantum_functions/annotation_parser.py +9 -11
- classiq/quantum_functions/function_parser.py +1 -1
- classiq/quantum_functions/quantum_function.py +3 -3
- classiq/quantum_register.py +17 -9
- {classiq-0.37.0.dist-info → classiq-0.38.0.dist-info}/METADATA +2 -1
- {classiq-0.37.0.dist-info → classiq-0.38.0.dist-info}/RECORD +222 -186
- {classiq-0.37.0.dist-info → classiq-0.38.0.dist-info}/WHEEL +1 -1
- classiq/interface/generator/expressions/qmod_qnum_proxy.py +0 -22
- classiq/interface/generator/types/builtin_struct_declarations/qaoa_declarations.py +0 -23
- classiq/interface/generator/types/combinatorial_problem.py +0 -26
- classiq/interface/model/numeric_reinterpretation.py +0 -25
- classiq/interface/model/operator_synthesis_data.py +0 -48
- classiq/model/function_handler.pyi +0 -152
@@ -1,4 +1,4 @@
|
|
1
|
-
from typing import List, Optional
|
1
|
+
from typing import Any, Dict, List, Optional
|
2
2
|
|
3
3
|
import pydantic
|
4
4
|
from pydantic import BaseModel
|
@@ -6,6 +6,7 @@ from pydantic import BaseModel
|
|
6
6
|
from classiq.interface.helpers.custom_pydantic_types import PydanticAlphaParamCVAR
|
7
7
|
|
8
8
|
from classiq._internals.enum_utils import StrEnum
|
9
|
+
from classiq.exceptions import ClassiqValueError
|
9
10
|
|
10
11
|
|
11
12
|
class CostType(StrEnum):
|
@@ -33,10 +34,10 @@ class OptimizerPreferences(BaseModel):
|
|
33
34
|
max_iteration: pydantic.PositiveInt = pydantic.Field(
|
34
35
|
default=100, description="Maximal number of optimizer iterations"
|
35
36
|
)
|
36
|
-
tolerance: pydantic.PositiveFloat = pydantic.Field(
|
37
|
+
tolerance: Optional[pydantic.PositiveFloat] = pydantic.Field(
|
37
38
|
default=None, description="Final accuracy in the optimization"
|
38
39
|
)
|
39
|
-
step_size: pydantic.PositiveFloat = pydantic.Field(
|
40
|
+
step_size: Optional[pydantic.PositiveFloat] = pydantic.Field(
|
40
41
|
default=None,
|
41
42
|
description="step size for numerically " "calculating the gradient",
|
42
43
|
)
|
@@ -54,30 +55,36 @@ class OptimizerPreferences(BaseModel):
|
|
54
55
|
)
|
55
56
|
|
56
57
|
@pydantic.validator("tolerance", pre=True, always=True)
|
57
|
-
def check_tolerance(
|
58
|
+
def check_tolerance(
|
59
|
+
cls, tolerance: Optional[pydantic.PositiveFloat], values: Dict[str, Any]
|
60
|
+
) -> Optional[pydantic.PositiveFloat]:
|
58
61
|
optimizer_type = values.get("type")
|
59
62
|
if tolerance is not None and optimizer_type == OptimizerType.SPSA:
|
60
|
-
raise
|
63
|
+
raise ClassiqValueError("No tolerance param for SPSA optimizer")
|
61
64
|
|
62
65
|
if tolerance is None and optimizer_type != OptimizerType.SPSA:
|
63
|
-
tolerance = 0.001
|
66
|
+
tolerance = pydantic.PositiveFloat(0.001)
|
64
67
|
|
65
68
|
return tolerance
|
66
69
|
|
67
70
|
@pydantic.validator("step_size", pre=True, always=True)
|
68
|
-
def check_step_size(
|
71
|
+
def check_step_size(
|
72
|
+
cls, step_size: Optional[pydantic.PositiveFloat], values: Dict[str, Any]
|
73
|
+
) -> Optional[pydantic.PositiveFloat]:
|
69
74
|
optimizer_type = values.get("name")
|
70
75
|
if step_size is not None and optimizer_type not in (
|
71
76
|
OptimizerType.L_BFGS_B,
|
72
77
|
OptimizerType.ADAM,
|
73
78
|
):
|
74
|
-
raise
|
79
|
+
raise ClassiqValueError(
|
80
|
+
"Use step_size only for L_BFGS_B or ADAM optimizers."
|
81
|
+
)
|
75
82
|
|
76
83
|
if step_size is None and optimizer_type in (
|
77
84
|
OptimizerType.L_BFGS_B,
|
78
85
|
OptimizerType.ADAM,
|
79
86
|
):
|
80
|
-
step_size = 0.05
|
87
|
+
step_size = pydantic.PositiveFloat(0.05)
|
81
88
|
|
82
89
|
return step_size
|
83
90
|
|
@@ -91,7 +98,7 @@ class CombinatorialOptimizer(OptimizerPreferences):
|
|
91
98
|
default=CostType.CVAR,
|
92
99
|
description="Summarizing method of the measured bit strings",
|
93
100
|
)
|
94
|
-
alpha_cvar: PydanticAlphaParamCVAR = pydantic.Field(
|
101
|
+
alpha_cvar: Optional[PydanticAlphaParamCVAR] = pydantic.Field(
|
95
102
|
default=None, description="Parameter for the CVAR summarizing method"
|
96
103
|
)
|
97
104
|
is_maximization: bool = pydantic.Field(
|
@@ -104,12 +111,14 @@ class CombinatorialOptimizer(OptimizerPreferences):
|
|
104
111
|
)
|
105
112
|
|
106
113
|
@pydantic.validator("alpha_cvar", pre=True, always=True)
|
107
|
-
def check_alpha_cvar(
|
114
|
+
def check_alpha_cvar(
|
115
|
+
cls, alpha_cvar: Optional[PydanticAlphaParamCVAR], values: Dict[str, Any]
|
116
|
+
) -> Optional[PydanticAlphaParamCVAR]:
|
108
117
|
cost_type = values.get("cost_type")
|
109
118
|
if alpha_cvar is not None and cost_type != CostType.CVAR:
|
110
|
-
raise
|
119
|
+
raise ClassiqValueError("Use CVAR params only for CostType.CVAR.")
|
111
120
|
|
112
121
|
if alpha_cvar is None and cost_type == CostType.CVAR:
|
113
|
-
alpha_cvar = 0.2
|
122
|
+
alpha_cvar = PydanticAlphaParamCVAR(0.2)
|
114
123
|
|
115
124
|
return alpha_cvar
|
@@ -6,7 +6,7 @@ from typing import Any, Dict, Optional, Tuple, Union
|
|
6
6
|
import pydantic
|
7
7
|
from pydantic import BaseModel
|
8
8
|
|
9
|
-
from classiq.interface.backend.ionq import
|
9
|
+
from classiq.interface.backend.ionq.ionq_quantum_program import IonqQuantumCircuit
|
10
10
|
from classiq.interface.backend.pydantic_backend import PydanticArgumentNameType
|
11
11
|
from classiq.interface.executor.quantum_instruction_set import QuantumInstructionSet
|
12
12
|
from classiq.interface.executor.register_initialization import RegisterInitialization
|
@@ -14,15 +14,17 @@ from classiq.interface.generator.synthesis_metadata.synthesis_execution_data imp
|
|
14
14
|
ExecutionData,
|
15
15
|
)
|
16
16
|
|
17
|
+
from classiq.exceptions import ClassiqValueError
|
18
|
+
|
17
19
|
Arguments = Dict[PydanticArgumentNameType, Any]
|
18
20
|
MultipleArguments = Tuple[Arguments, ...]
|
19
|
-
CodeType =
|
21
|
+
CodeType = str
|
20
22
|
RegistersInitialization = Dict[str, RegisterInitialization]
|
21
23
|
Qubits = Tuple[int, ...]
|
22
24
|
OutputQubitsMap = Dict[str, Qubits]
|
23
25
|
|
24
26
|
|
25
|
-
class
|
27
|
+
class QuantumBaseCode(BaseModel):
|
26
28
|
syntax: QuantumInstructionSet = pydantic.Field(
|
27
29
|
default=QuantumInstructionSet.QASM, description="The syntax of the program."
|
28
30
|
)
|
@@ -31,17 +33,21 @@ class QuantumBaseProgram(BaseModel):
|
|
31
33
|
)
|
32
34
|
|
33
35
|
@pydantic.validator("code")
|
34
|
-
def load_quantum_program(
|
35
|
-
|
36
|
-
|
37
|
-
|
36
|
+
def load_quantum_program(
|
37
|
+
cls, code: Union[CodeType, IonqQuantumCircuit], values: Dict[str, Any]
|
38
|
+
) -> CodeType:
|
38
39
|
syntax = values.get("syntax")
|
39
|
-
if
|
40
|
-
|
40
|
+
if isinstance(code, IonqQuantumCircuit):
|
41
|
+
if syntax != QuantumInstructionSet.IONQ:
|
42
|
+
raise ClassiqValueError(
|
43
|
+
f"Invalid code type {type(code)} for syntax: {syntax}"
|
44
|
+
)
|
45
|
+
return code.json()
|
46
|
+
|
41
47
|
return code
|
42
48
|
|
43
49
|
|
44
|
-
class
|
50
|
+
class QuantumCode(QuantumBaseCode):
|
45
51
|
arguments: MultipleArguments = pydantic.Field(
|
46
52
|
default=(),
|
47
53
|
description="The parameters dictionary for a parametrized quantum program.",
|
@@ -68,10 +74,10 @@ class QuantumProgram(QuantumBaseProgram):
|
|
68
74
|
QuantumInstructionSet.QSHARP,
|
69
75
|
QuantumInstructionSet.QASM,
|
70
76
|
):
|
71
|
-
raise
|
77
|
+
raise ClassiqValueError("Only QASM or Q# programs support arguments")
|
72
78
|
|
73
79
|
if values.get("syntax") == QuantumInstructionSet.QSHARP and len(arguments) > 1:
|
74
|
-
raise
|
80
|
+
raise ClassiqValueError(
|
75
81
|
f"Q# programs supports only one group of arguments. {len(arguments)} given"
|
76
82
|
)
|
77
83
|
|
@@ -87,7 +93,7 @@ class QuantumProgram(QuantumBaseProgram):
|
|
87
93
|
synthesis_execution_data is not None
|
88
94
|
and values.get("syntax") is not QuantumInstructionSet.QASM
|
89
95
|
):
|
90
|
-
raise
|
96
|
+
raise ClassiqValueError("Only QASM supports the requested configuration")
|
91
97
|
|
92
98
|
return synthesis_execution_data
|
93
99
|
|
@@ -96,9 +102,9 @@ class QuantumProgram(QuantumBaseProgram):
|
|
96
102
|
file_path: Union[str, Path],
|
97
103
|
syntax: Optional[Union[str, QuantumInstructionSet]] = None,
|
98
104
|
arguments: MultipleArguments = (),
|
99
|
-
) ->
|
105
|
+
) -> QuantumCode:
|
100
106
|
path = Path(file_path)
|
101
107
|
code = path.read_text()
|
102
108
|
if syntax is None:
|
103
109
|
syntax = QuantumInstructionSet.from_suffix(path.suffix.lstrip("."))
|
104
|
-
return
|
110
|
+
return QuantumCode(syntax=syntax, code=code, arguments=arguments)
|
@@ -1,4 +1,5 @@
|
|
1
1
|
from classiq._internals.enum_utils import StrEnum
|
2
|
+
from classiq.exceptions import ClassiqValueError
|
2
3
|
|
3
4
|
|
4
5
|
class QuantumInstructionSet(StrEnum):
|
@@ -14,4 +15,4 @@ class QuantumInstructionSet(StrEnum):
|
|
14
15
|
return QuantumInstructionSet.QSHARP
|
15
16
|
if suffix == "ionq":
|
16
17
|
return QuantumInstructionSet.IONQ
|
17
|
-
raise
|
18
|
+
raise ClassiqValueError("Illegal suffix")
|
@@ -30,9 +30,7 @@ class RegisterInitialization(pydantic.BaseModel):
|
|
30
30
|
initial_condition: int = values.get("initial_condition", 0)
|
31
31
|
name: str = values.get("name", "")
|
32
32
|
|
33
|
-
initial_condition_length = number_utils.size(
|
34
|
-
initial_condition, machine_precision=number_utils.MAX_FRACTION_PLACES
|
35
|
-
)
|
33
|
+
initial_condition_length = number_utils.size(initial_condition)
|
36
34
|
register_length = len(qubits)
|
37
35
|
if initial_condition_length > register_length:
|
38
36
|
raise ClassiqStateInitializationError(
|
@@ -17,7 +17,7 @@ import pydantic
|
|
17
17
|
from pydantic import BaseModel
|
18
18
|
from typing_extensions import TypeAlias
|
19
19
|
|
20
|
-
from classiq.interface.executor.
|
20
|
+
from classiq.interface.executor.quantum_code import OutputQubitsMap, Qubits
|
21
21
|
from classiq.interface.generator.arith import number_utils
|
22
22
|
from classiq.interface.generator.complex_type import Complex
|
23
23
|
from classiq.interface.generator.functions.classical_type import QmodPyObject
|
@@ -44,6 +44,9 @@ class SampledState(BaseModel):
|
|
44
44
|
state: ParsedState
|
45
45
|
shots: MeasuredShots
|
46
46
|
|
47
|
+
def __repr__(self) -> str:
|
48
|
+
return f"{self.state}: {self.shots}"
|
49
|
+
|
47
50
|
|
48
51
|
ParsedCounts: TypeAlias = List[SampledState]
|
49
52
|
|
@@ -97,6 +100,28 @@ def get_sampled_state(
|
|
97
100
|
return None
|
98
101
|
|
99
102
|
|
103
|
+
def reduce_parsed_states(
|
104
|
+
parsed_states: ParsedStates, outputs: Tuple[Name, ...]
|
105
|
+
) -> ParsedStates:
|
106
|
+
return {
|
107
|
+
state: {
|
108
|
+
output: value for output, value in parsed_state.items() if output in outputs
|
109
|
+
}
|
110
|
+
for state, parsed_state in parsed_states.items()
|
111
|
+
}
|
112
|
+
|
113
|
+
|
114
|
+
def get_parsed_counts(counts: Counts, parsed_states: ParsedStates) -> ParsedCounts:
|
115
|
+
parsed_counts: ParsedCounts = []
|
116
|
+
for bitstring, count in counts.items():
|
117
|
+
parsed_state = parsed_states[bitstring]
|
118
|
+
if sampled_state := get_sampled_state(parsed_counts, parsed_state):
|
119
|
+
sampled_state.shots += count
|
120
|
+
else:
|
121
|
+
parsed_counts.append(SampledState(state=parsed_state, shots=count))
|
122
|
+
return sorted(parsed_counts, key=lambda k: k.shots, reverse=True)
|
123
|
+
|
124
|
+
|
100
125
|
class ExecutionDetails(BaseModel, QmodPyObject):
|
101
126
|
vendor_format_result: Dict[str, Any] = pydantic.Field(
|
102
127
|
..., description="Result in proprietary vendor format"
|
@@ -155,14 +180,7 @@ class ExecutionDetails(BaseModel, QmodPyObject):
|
|
155
180
|
|
156
181
|
@property
|
157
182
|
def parsed_counts(self) -> ParsedCounts:
|
158
|
-
|
159
|
-
for bitstring, count in self.counts.items():
|
160
|
-
parsed_state = self.parsed_states[bitstring]
|
161
|
-
if sampled_state := get_sampled_state(parsed_counts, parsed_state):
|
162
|
-
sampled_state.shots += count
|
163
|
-
else:
|
164
|
-
parsed_counts.append(SampledState(state=parsed_state, shots=count))
|
165
|
-
return sorted(parsed_counts, key=lambda k: k.shots, reverse=True)
|
183
|
+
return get_parsed_counts(self.counts, self.parsed_states)
|
166
184
|
|
167
185
|
@property
|
168
186
|
def parsed_state_vector(self) -> Optional[ParsedStateVector]:
|
@@ -223,6 +241,17 @@ class ExecutionDetails(BaseModel, QmodPyObject):
|
|
223
241
|
reduced_counts[reduced_strs] += state_count
|
224
242
|
return dict(reduced_counts)
|
225
243
|
|
244
|
+
def parsed_counts_of_outputs(
|
245
|
+
self, output_names: Union[Name, Tuple[Name, ...]]
|
246
|
+
) -> ParsedCounts:
|
247
|
+
if isinstance(output_names, Name):
|
248
|
+
output_names = (output_names,)
|
249
|
+
if any(name not in self.output_qubits_map for name in output_names):
|
250
|
+
raise ClassiqError(_UNAVAILABLE_OUTPUT_ERROR_MSG)
|
251
|
+
|
252
|
+
reduced_parsed_states = reduce_parsed_states(self.parsed_states, output_names)
|
253
|
+
return get_parsed_counts(self.counts, reduced_parsed_states)
|
254
|
+
|
226
255
|
def register_output_from_qubits(self, qubits: Tuple[int, ...]) -> Dict[float, int]:
|
227
256
|
register_output: Dict[float, int] = {}
|
228
257
|
value_from_str_bin = functools.partial(
|
@@ -273,7 +302,9 @@ class EstimationResults(VersionedModel):
|
|
273
302
|
def __len__(self) -> int:
|
274
303
|
return len(self.results)
|
275
304
|
|
276
|
-
def __iter__(self) -> Iterator[EstimationResult]: # type: ignore
|
305
|
+
def __iter__(self) -> Iterator[EstimationResult]: # type: ignore[override]
|
306
|
+
# TODO This is a bug waiting to happen. We change the meaning of
|
307
|
+
# __iter__ in a derived class.
|
277
308
|
return iter(self.results)
|
278
309
|
|
279
310
|
def __getitem__(self, index: int) -> EstimationResult:
|
@@ -3,12 +3,15 @@ from typing import Any, Dict, Optional, Union
|
|
3
3
|
import pydantic
|
4
4
|
|
5
5
|
from classiq.interface.generator.expressions.enums.finance_functions import (
|
6
|
+
FINANCE_FUNCTION_STRING,
|
6
7
|
FinanceFunctionType,
|
7
8
|
)
|
8
9
|
from classiq.interface.helpers.custom_pydantic_types import (
|
9
10
|
PydanticNonZeroProbabilityFloat,
|
10
11
|
)
|
11
12
|
|
13
|
+
from classiq.exceptions import ClassiqValueError
|
14
|
+
|
12
15
|
|
13
16
|
class FunctionCondition(pydantic.BaseModel):
|
14
17
|
threshold: float
|
@@ -22,8 +25,9 @@ class FunctionCondition(pydantic.BaseModel):
|
|
22
25
|
|
23
26
|
|
24
27
|
class FinanceFunctionInput(pydantic.BaseModel):
|
25
|
-
f:
|
26
|
-
description="
|
28
|
+
f: FinanceFunctionType = pydantic.Field(
|
29
|
+
description="An enumeration of the wanted financial function: VaR, expected "
|
30
|
+
"shortfall, European call options or x^2"
|
27
31
|
)
|
28
32
|
variable: str = pydantic.Field(
|
29
33
|
default="x", description="Variable/s of the function"
|
@@ -45,13 +49,20 @@ class FinanceFunctionInput(pydantic.BaseModel):
|
|
45
49
|
description="The required probability on the tail of the distribution (1 - percentile)",
|
46
50
|
)
|
47
51
|
|
52
|
+
@pydantic.validator("f", pre=True)
|
53
|
+
def _convert_f_if_str(cls, f: Any) -> FinanceFunctionType:
|
54
|
+
# Keep this for backwards-compatible string support
|
55
|
+
if f in FINANCE_FUNCTION_STRING:
|
56
|
+
return FINANCE_FUNCTION_STRING[f]
|
57
|
+
return f
|
58
|
+
|
48
59
|
@pydantic.validator("use_chebyshev_polynomial_approximation")
|
49
60
|
def _validate_polynomial_flag(
|
50
61
|
cls, use_chebyshev_flag: bool, values: Dict[str, Any]
|
51
62
|
) -> bool:
|
52
63
|
if use_chebyshev_flag ^ (values.get("polynomial_degree") is None):
|
53
64
|
return use_chebyshev_flag
|
54
|
-
raise
|
65
|
+
raise ClassiqValueError(
|
55
66
|
"Degree must be positive and use_chebyshev_polynomial_approximation set to True"
|
56
67
|
)
|
57
68
|
|
@@ -72,7 +83,9 @@ class FinanceFunctionInput(pydantic.BaseModel):
|
|
72
83
|
values: Dict[str, Any],
|
73
84
|
) -> Optional[PydanticNonZeroProbabilityFloat]:
|
74
85
|
if values.get("f") == FinanceFunctionType.SHORTFALL and not tail_probability:
|
75
|
-
raise
|
86
|
+
raise ClassiqValueError(
|
87
|
+
"Tail probability must be set for expected shortfall"
|
88
|
+
)
|
76
89
|
return tail_probability
|
77
90
|
|
78
91
|
class Config:
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import math
|
2
|
-
from typing import List, Optional, Tuple
|
2
|
+
from typing import List, Literal, Optional, Tuple
|
3
3
|
|
4
4
|
import pydantic
|
5
5
|
|
@@ -8,6 +8,8 @@ from classiq.interface.helpers.custom_pydantic_types import PydanticProbabilityF
|
|
8
8
|
|
9
9
|
|
10
10
|
class GaussianModelInput(FinanceModelInput):
|
11
|
+
kind: Literal["gaussian"] = pydantic.Field(default="gaussian")
|
12
|
+
|
11
13
|
num_qubits: pydantic.PositiveInt = pydantic.Field(
|
12
14
|
description="The number of qubits represent"
|
13
15
|
"the latent normal random variable Z (Resolution of "
|
@@ -1,4 +1,4 @@
|
|
1
|
-
from typing import Tuple
|
1
|
+
from typing import Literal, Tuple
|
2
2
|
|
3
3
|
import numpy as np
|
4
4
|
import pydantic
|
@@ -7,6 +7,8 @@ from classiq.interface.finance.model_input import FinanceModelInput
|
|
7
7
|
|
8
8
|
|
9
9
|
class LogNormalModelInput(FinanceModelInput):
|
10
|
+
kind: Literal["log_normal"] = pydantic.Field(default="log_normal")
|
11
|
+
|
10
12
|
num_qubits: pydantic.PositiveInt = pydantic.Field(
|
11
13
|
description="Number of qubits to represent the probability."
|
12
14
|
)
|
@@ -20,6 +20,7 @@ from classiq.interface.generator.function_params import (
|
|
20
20
|
from classiq.interface.helpers.custom_pydantic_types import PydanticExpressionStr
|
21
21
|
|
22
22
|
from classiq._internals.enum_utils import StrEnum
|
23
|
+
from classiq.exceptions import ClassiqValueError
|
23
24
|
|
24
25
|
AMPLITUDE_IO_NAME = "AMPLITUDE"
|
25
26
|
TARGET_OUTPUT_NAME = "TARGET"
|
@@ -66,14 +67,17 @@ class AmplitudeLoading(FunctionParams):
|
|
66
67
|
not_allowed = literals.intersection(FORBIDDEN_LITERALS)
|
67
68
|
variables = literals.difference(SUPPORTED_FUNC_NAMES)
|
68
69
|
if not_allowed:
|
69
|
-
raise
|
70
|
+
raise ClassiqValueError(
|
71
|
+
f"The following names: {not_allowed} are not allowed"
|
72
|
+
)
|
70
73
|
|
71
74
|
if len(variables) != 1:
|
72
|
-
raise
|
75
|
+
raise ClassiqValueError(f"{variables} must contain exactly single variable")
|
73
76
|
return values
|
74
77
|
|
75
78
|
def _create_ios(self) -> None:
|
76
79
|
self._inputs = {
|
80
|
+
TARGET_OUTPUT_NAME: RegisterUserInput(name=TARGET_OUTPUT_NAME, size=1),
|
77
81
|
AMPLITUDE_IO_NAME: RegisterUserInput(
|
78
82
|
name=AMPLITUDE_IO_NAME, size=self.size
|
79
83
|
),
|
@@ -82,7 +86,6 @@ class AmplitudeLoading(FunctionParams):
|
|
82
86
|
TARGET_OUTPUT_NAME: RegisterUserInput(name=TARGET_OUTPUT_NAME, size=1),
|
83
87
|
**self._inputs,
|
84
88
|
}
|
85
|
-
self._create_zero_input_registers({TARGET_OUTPUT_NAME: 1})
|
86
89
|
|
87
90
|
@property
|
88
91
|
def variable(self) -> str:
|
@@ -2,6 +2,7 @@ from classiq.interface.generator.builtin_api_builder import (
|
|
2
2
|
populate_builtin_declarations,
|
3
3
|
)
|
4
4
|
|
5
|
+
from .arithmetic_declarations import * # noqa: F403
|
5
6
|
from .chemistry_declarations import * # noqa: F403
|
6
7
|
from .combinatorial_optimization_declarations import * # noqa: F403
|
7
8
|
from .entangler_declarations import * # noqa: F403
|
@@ -0,0 +1,14 @@
|
|
1
|
+
from classiq.interface.generator.functions.classical_function_declaration import (
|
2
|
+
ClassicalFunctionDeclaration,
|
3
|
+
)
|
4
|
+
from classiq.interface.generator.functions.classical_type import Integer, Real
|
5
|
+
|
6
|
+
qft_const_adder_phase = ClassicalFunctionDeclaration(
|
7
|
+
name="qft_const_adder_phase",
|
8
|
+
param_decls={
|
9
|
+
"bit_index": Integer(),
|
10
|
+
"value": Integer(),
|
11
|
+
"reg_len": Integer(),
|
12
|
+
},
|
13
|
+
return_type=Real(),
|
14
|
+
)
|
@@ -6,10 +6,10 @@ from classiq.interface.generator.arith.register_user_input import RegisterArithm
|
|
6
6
|
RegisterOrConst = Union[RegisterArithmeticInfo, float]
|
7
7
|
|
8
8
|
|
9
|
-
def fraction_places(argument: RegisterOrConst
|
9
|
+
def fraction_places(argument: RegisterOrConst) -> int:
|
10
10
|
if isinstance(argument, RegisterArithmeticInfo):
|
11
11
|
return argument.fraction_places
|
12
|
-
return number_utils.fraction_places(argument
|
12
|
+
return number_utils.fraction_places(argument)
|
13
13
|
|
14
14
|
|
15
15
|
def integer_part_size(argument: RegisterOrConst) -> int:
|
@@ -18,10 +18,10 @@ def integer_part_size(argument: RegisterOrConst) -> int:
|
|
18
18
|
return number_utils.integer_part_size(argument)
|
19
19
|
|
20
20
|
|
21
|
-
def size(argument: RegisterOrConst
|
21
|
+
def size(argument: RegisterOrConst) -> int:
|
22
22
|
if isinstance(argument, RegisterArithmeticInfo):
|
23
23
|
return argument.size
|
24
|
-
return number_utils.size(argument
|
24
|
+
return number_utils.size(argument)
|
25
25
|
|
26
26
|
|
27
27
|
def is_signed(argument: RegisterOrConst) -> bool:
|
@@ -46,3 +46,13 @@ def bounds(argument: RegisterOrConst) -> Tuple[float, float]:
|
|
46
46
|
if isinstance(argument, RegisterArithmeticInfo):
|
47
47
|
return argument.bounds
|
48
48
|
return argument, argument
|
49
|
+
|
50
|
+
|
51
|
+
def limit_fraction_places(
|
52
|
+
argument: RegisterOrConst, *, machine_precision: int
|
53
|
+
) -> RegisterOrConst:
|
54
|
+
if isinstance(argument, RegisterArithmeticInfo):
|
55
|
+
return argument.limit_fraction_places(machine_precision)
|
56
|
+
return number_utils.limit_fraction_places(
|
57
|
+
argument, machine_precision=machine_precision
|
58
|
+
)
|
@@ -21,6 +21,8 @@ from classiq.interface.model.quantum_type import (
|
|
21
21
|
register_info_to_quantum_type,
|
22
22
|
)
|
23
23
|
|
24
|
+
from classiq.exceptions import ClassiqValueError
|
25
|
+
|
24
26
|
ARITHMETIC_EXPRESSION_TARGET_NAME: str = "arithmetic_target"
|
25
27
|
ARITHMETIC_EXPRESSION_RESULT_NAME: str = "expression_result"
|
26
28
|
|
@@ -47,7 +49,7 @@ class Arithmetic(ArithmeticExpressionABC):
|
|
47
49
|
degree or operation_allows_target(id2op(node))
|
48
50
|
for node, degree in graph.out_degree
|
49
51
|
):
|
50
|
-
raise
|
52
|
+
raise ClassiqValueError("Expression does not support target assignment")
|
51
53
|
|
52
54
|
def _create_ios(self) -> None:
|
53
55
|
self._inputs = {
|
@@ -2,23 +2,16 @@ from typing import Callable, Dict, List
|
|
2
2
|
|
3
3
|
from typing_extensions import TypeAlias
|
4
4
|
|
5
|
-
from classiq.interface.generator.arith
|
6
|
-
RegisterOrConst,
|
7
|
-
fraction_places,
|
8
|
-
)
|
5
|
+
from classiq.interface.generator.arith import argument_utils
|
9
6
|
from classiq.interface.generator.arith.binary_ops import BOOLEAN_OP_WITH_FRACTIONS_ERROR
|
10
7
|
|
11
8
|
from classiq.exceptions import ClassiqArithmeticError
|
12
9
|
|
13
|
-
ArgTypeValidator: TypeAlias = Callable[[List[RegisterOrConst]
|
10
|
+
ArgTypeValidator: TypeAlias = Callable[[List[argument_utils.RegisterOrConst]], None]
|
14
11
|
|
15
12
|
|
16
|
-
def _validate_bitwise_op_args(
|
17
|
-
|
18
|
-
) -> None:
|
19
|
-
if any(
|
20
|
-
fraction_places(arg, machine_precision=machine_precision) > 0 for arg in args
|
21
|
-
):
|
13
|
+
def _validate_bitwise_op_args(args: List[argument_utils.RegisterOrConst]) -> None:
|
14
|
+
if any(argument_utils.fraction_places(arg) > 0 for arg in args):
|
22
15
|
raise ClassiqArithmeticError(BOOLEAN_OP_WITH_FRACTIONS_ERROR)
|
23
16
|
|
24
17
|
|
@@ -30,8 +23,14 @@ arg_type_validator_map: Dict[str, ArgTypeValidator] = dict(
|
|
30
23
|
|
31
24
|
|
32
25
|
def validate_operation_arg_types(
|
33
|
-
operation: str,
|
26
|
+
operation: str,
|
27
|
+
arguments: List[argument_utils.RegisterOrConst],
|
28
|
+
machine_precision: int,
|
34
29
|
) -> None:
|
35
30
|
if operation not in arg_type_validator_map:
|
36
31
|
return
|
37
|
-
|
32
|
+
limited_args = [
|
33
|
+
argument_utils.limit_fraction_places(arg, machine_precision=machine_precision)
|
34
|
+
for arg in arguments
|
35
|
+
]
|
36
|
+
arg_type_validator_map[operation](limited_args)
|
@@ -17,6 +17,9 @@ from classiq.interface.generator.arith.arithmetic_expression_validator import (
|
|
17
17
|
from classiq.interface.generator.arith.arithmetic_result_builder import (
|
18
18
|
validate_arithmetic_result_type,
|
19
19
|
)
|
20
|
+
from classiq.interface.generator.arith.machine_precision import (
|
21
|
+
DEFAULT_MACHINE_PRECISION,
|
22
|
+
)
|
20
23
|
from classiq.interface.generator.arith.register_user_input import RegisterArithmeticInfo
|
21
24
|
from classiq.interface.generator.arith.uncomputation_methods import UncomputationMethods
|
22
25
|
from classiq.interface.generator.expressions.expression_constants import (
|
@@ -36,7 +39,7 @@ ValidDefinitions: TypeAlias = Union[
|
|
36
39
|
|
37
40
|
class ArithmeticExpressionABC(abc.ABC, FunctionParams):
|
38
41
|
uncomputation_method: UncomputationMethods = UncomputationMethods.optimized
|
39
|
-
machine_precision: pydantic.NonNegativeInt =
|
42
|
+
machine_precision: pydantic.NonNegativeInt = DEFAULT_MACHINE_PRECISION
|
40
43
|
expression: PydanticExpressionStr
|
41
44
|
definitions: Dict[str, ValidDefinitions]
|
42
45
|
qubit_count: Optional[pydantic.NonNegativeInt] = None
|
@@ -19,7 +19,9 @@ from classiq.interface.generator.arith.ast_node_rewrite import (
|
|
19
19
|
from classiq.exceptions import ClassiqArithmeticError
|
20
20
|
|
21
21
|
_MULTIPLE_RESULTS_ERROR_MESSAGE: str = "Expression cannot contain multiple result"
|
22
|
-
|
22
|
+
_UNEXPECTED_ARITHMETIC_ERROR_MESSAGE: str = (
|
23
|
+
"Unexpected arithmetic error: trivial expression. Please contact support."
|
24
|
+
)
|
23
25
|
_ALLOWED_MULTI_ARGUMENT_FUNCTIONS = ("min", "max")
|
24
26
|
Node = Union[str, float, int]
|
25
27
|
|
@@ -34,6 +36,10 @@ class ExpressionVisitor(ExpressionValidator):
|
|
34
36
|
super().__init__(supported_nodes, expression_type, supported_functions)
|
35
37
|
self.graph = nx.DiGraph()
|
36
38
|
|
39
|
+
@classmethod
|
40
|
+
def rewrite_ast(cls, expression_ast: AST) -> AST:
|
41
|
+
return AstNodeRewrite().visit(expression_ast)
|
42
|
+
|
37
43
|
def visit_Compare(self, node: ast.Compare) -> None:
|
38
44
|
self.validate_Compare(node)
|
39
45
|
self.update_graph(node, node.left, node.comparators[0])
|
@@ -122,7 +128,7 @@ class InDegreeLimiter:
|
|
122
128
|
if num_results > 1:
|
123
129
|
raise ClassiqArithmeticError(_MULTIPLE_RESULTS_ERROR_MESSAGE)
|
124
130
|
elif num_results == 0:
|
125
|
-
raise ClassiqArithmeticError(
|
131
|
+
raise ClassiqArithmeticError(_UNEXPECTED_ARITHMETIC_ERROR_MESSAGE)
|
126
132
|
return graph
|
127
133
|
|
128
134
|
|