classiq 0.87.0__py3-none-any.whl → 0.88.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.
Potentially problematic release.
This version of classiq might be problematic. Click here for more details.
- classiq/applications/__init__.py +1 -2
- classiq/applications/combinatorial_helpers/combinatorial_problem_utils.py +1 -1
- classiq/applications/hamiltonian/pauli_decomposition.py +1 -1
- classiq/evaluators/qmod_annotated_expression.py +30 -7
- classiq/evaluators/qmod_expression_visitors/qmod_expression_bwc.py +0 -5
- classiq/evaluators/qmod_expression_visitors/qmod_expression_evaluator.py +18 -11
- classiq/evaluators/qmod_expression_visitors/qmod_expression_renamer.py +14 -7
- classiq/evaluators/qmod_expression_visitors/qmod_expression_simplifier.py +39 -16
- classiq/evaluators/qmod_node_evaluators/attribute_evaluation.py +1 -1
- classiq/evaluators/qmod_node_evaluators/classical_function_evaluation.py +18 -8
- classiq/evaluators/qmod_node_evaluators/compare_evaluation.py +8 -0
- classiq/evaluators/qmod_node_evaluators/constant_evaluation.py +4 -1
- classiq/evaluators/qmod_node_evaluators/numeric_attrs_utils.py +1 -1
- classiq/evaluators/qmod_node_evaluators/struct_instantiation_evaluation.py +1 -1
- classiq/evaluators/qmod_node_evaluators/subscript_evaluation.py +3 -3
- classiq/evaluators/qmod_node_evaluators/utils.py +1 -1
- classiq/evaluators/qmod_type_inference/classical_type_inference.py +4 -4
- classiq/evaluators/qmod_type_inference/quantum_type_inference.py +38 -0
- classiq/evaluators/type_type_match.py +1 -1
- classiq/execution/execution_session.py +17 -2
- classiq/interface/_version.py +1 -1
- classiq/interface/execution/primitives.py +1 -0
- classiq/interface/generator/application_apis/__init__.py +0 -1
- classiq/interface/generator/expressions/atomic_expression_functions.py +0 -2
- classiq/interface/generator/function_param_list.py +0 -4
- classiq/interface/generator/functions/classical_type.py +8 -0
- classiq/interface/generator/functions/type_name.py +6 -0
- classiq/interface/generator/transpiler_basis_gates.py +5 -1
- classiq/interface/generator/types/builtin_enum_declarations.py +0 -8
- classiq/interface/model/classical_if.py +16 -8
- classiq/interface/model/classical_parameter_declaration.py +4 -0
- classiq/interface/model/port_declaration.py +12 -0
- classiq/interface/model/quantum_function_declaration.py +12 -0
- classiq/interface/model/quantum_type.py +56 -0
- classiq/interface/pretty_print/expression_to_qmod.py +3 -17
- classiq/model_expansions/quantum_operations/allocate.py +1 -1
- classiq/model_expansions/quantum_operations/handle_evaluator.py +2 -8
- classiq/open_library/functions/__init__.py +1 -0
- classiq/open_library/functions/lcu.py +2 -2
- classiq/open_library/functions/state_preparation.py +47 -5
- classiq/qmod/builtins/__init__.py +0 -3
- classiq/qmod/builtins/classical_functions.py +0 -28
- classiq/qmod/builtins/enums.py +24 -18
- classiq/qmod/builtins/functions/__init__.py +0 -5
- classiq/qmod/builtins/operations.py +142 -0
- classiq/qmod/builtins/structs.py +0 -11
- classiq/qmod/native/pretty_printer.py +1 -1
- classiq/qmod/pretty_print/expression_to_python.py +3 -6
- classiq/qmod/pretty_print/pretty_printer.py +4 -1
- classiq/qmod/qmod_variable.py +94 -2
- classiq/qmod/semantics/annotation/call_annotation.py +4 -2
- classiq/qmod/semantics/annotation/qstruct_annotator.py +20 -5
- {classiq-0.87.0.dist-info → classiq-0.88.0.dist-info}/METADATA +3 -3
- {classiq-0.87.0.dist-info → classiq-0.88.0.dist-info}/RECORD +55 -67
- classiq/applications/finance/__init__.py +0 -15
- classiq/interface/finance/__init__.py +0 -0
- classiq/interface/finance/finance_modelling_params.py +0 -11
- classiq/interface/finance/function_input.py +0 -102
- classiq/interface/finance/gaussian_model_input.py +0 -50
- classiq/interface/finance/log_normal_model_input.py +0 -40
- classiq/interface/finance/model_input.py +0 -22
- classiq/interface/generator/application_apis/finance_declarations.py +0 -108
- classiq/interface/generator/expressions/enums/__init__.py +0 -0
- classiq/interface/generator/expressions/enums/finance_functions.py +0 -12
- classiq/interface/generator/finance.py +0 -107
- classiq/qmod/builtins/functions/finance.py +0 -34
- {classiq-0.87.0.dist-info → classiq-0.88.0.dist-info}/WHEEL +0 -0
|
@@ -340,6 +340,7 @@ class ExecutionSession:
|
|
|
340
340
|
initial_params: ExecutionParams,
|
|
341
341
|
max_iteration: int,
|
|
342
342
|
quantile: float = 1.0,
|
|
343
|
+
tolerance: Optional[float] = None,
|
|
343
344
|
) -> list[tuple[float, ExecutionParams]]:
|
|
344
345
|
"""
|
|
345
346
|
Minimizes the given cost function using the quantum program.
|
|
@@ -355,6 +356,7 @@ class ExecutionSession:
|
|
|
355
356
|
- The value is either a float or a list of floats.
|
|
356
357
|
max_iteration: The maximum number of iterations for the minimization.
|
|
357
358
|
quantile: The quantile to use for cost estimation.
|
|
359
|
+
tolerance: The tolerance for the minimization.
|
|
358
360
|
Returns:
|
|
359
361
|
A list of tuples, each containing the estimated cost and the corresponding parameters for that iteration.
|
|
360
362
|
`cost` is a float, and `parameters` is a dictionary matching the execution parameter format.
|
|
@@ -365,6 +367,7 @@ class ExecutionSession:
|
|
|
365
367
|
initial_params=initial_params,
|
|
366
368
|
max_iteration=max_iteration,
|
|
367
369
|
quantile=quantile,
|
|
370
|
+
tolerance=tolerance,
|
|
368
371
|
_check_deprecation=False,
|
|
369
372
|
)
|
|
370
373
|
result = job.get_minimization_result(_http_client=self._async_client)
|
|
@@ -379,6 +382,7 @@ class ExecutionSession:
|
|
|
379
382
|
initial_params: ExecutionParams,
|
|
380
383
|
max_iteration: int,
|
|
381
384
|
quantile: float = 1.0,
|
|
385
|
+
tolerance: Optional[float] = None,
|
|
382
386
|
*,
|
|
383
387
|
_check_deprecation: bool = True,
|
|
384
388
|
) -> ExecutionJob:
|
|
@@ -400,6 +404,7 @@ class ExecutionSession:
|
|
|
400
404
|
- The value is either a float or a list of floats.
|
|
401
405
|
max_iteration: The maximum number of iterations for the minimization.
|
|
402
406
|
quantile: The quantile to use for cost estimation.
|
|
407
|
+
tolerance: The tolerance for the minimization.
|
|
403
408
|
|
|
404
409
|
Returns:
|
|
405
410
|
The execution job.
|
|
@@ -424,6 +429,7 @@ class ExecutionSession:
|
|
|
424
429
|
initial_params=_initial_params,
|
|
425
430
|
max_iteration=max_iteration,
|
|
426
431
|
quantile=quantile,
|
|
432
|
+
tolerance=tolerance,
|
|
427
433
|
)
|
|
428
434
|
else:
|
|
429
435
|
_cost_function = self._hamiltonian_to_pauli_operator(cost_function)
|
|
@@ -432,6 +438,7 @@ class ExecutionSession:
|
|
|
432
438
|
initial_params=_initial_params,
|
|
433
439
|
max_iteration=max_iteration,
|
|
434
440
|
quantile=quantile,
|
|
441
|
+
tolerance=tolerance,
|
|
435
442
|
)
|
|
436
443
|
|
|
437
444
|
execution_primitives_input = PrimitivesInput(minimize=minimize)
|
|
@@ -545,10 +552,18 @@ class ExecutionSession:
|
|
|
545
552
|
name: create_qvar_from_quantum_type(reg.quantum_types, name)
|
|
546
553
|
for name, reg in circuit_output_types.items()
|
|
547
554
|
}
|
|
548
|
-
|
|
555
|
+
creator_parameters = inspect.signature(
|
|
556
|
+
qmod_expression_creator
|
|
557
|
+
).parameters.keys()
|
|
558
|
+
for name in creator_parameters:
|
|
549
559
|
if name not in symbolic_output:
|
|
550
560
|
raise ClassiqValueError(
|
|
551
|
-
f"
|
|
561
|
+
f"Expected cost function with parameters {tuple(symbolic_output.keys())} corresponding to the quantum program outputs, but found '{name}'. "
|
|
562
|
+
)
|
|
563
|
+
for name in symbolic_output:
|
|
564
|
+
if name not in creator_parameters:
|
|
565
|
+
raise ClassiqValueError(
|
|
566
|
+
f"Expected cost function with parameter '{name}' corresponding to the quantum program outputs. "
|
|
552
567
|
)
|
|
553
568
|
|
|
554
569
|
qmod_expression = qmod_expression_creator(**symbolic_output)
|
classiq/interface/_version.py
CHANGED
|
@@ -6,7 +6,6 @@ from .arithmetic_declarations import * # noqa: F403
|
|
|
6
6
|
from .chemistry_declarations import * # noqa: F403
|
|
7
7
|
from .combinatorial_optimization_declarations import * # noqa: F403
|
|
8
8
|
from .entangler_declarations import * # noqa: F403
|
|
9
|
-
from .finance_declarations import * # noqa: F403
|
|
10
9
|
from .qsvm_declarations import * # noqa: F403
|
|
11
10
|
|
|
12
11
|
populate_builtin_declarations(vars().values())
|
|
@@ -4,8 +4,6 @@ CLASSIQ_BUILTIN_CLASSICAL_FUNCTIONS = {
|
|
|
4
4
|
"hypercube_entangler_graph",
|
|
5
5
|
"grid_entangler_graph",
|
|
6
6
|
"qft_const_adder_phase",
|
|
7
|
-
"log_normal_finance_post_process",
|
|
8
|
-
"gaussian_finance_post_process",
|
|
9
7
|
"molecule_problem_to_hamiltonian",
|
|
10
8
|
"fock_hamiltonian_problem_to_hamiltonian",
|
|
11
9
|
"molecule_ground_state_solution_post_process",
|
|
@@ -33,7 +33,6 @@ from classiq.interface.generator.entangler_params import (
|
|
|
33
33
|
HypercubeEntangler,
|
|
34
34
|
TwoDimensionalEntangler,
|
|
35
35
|
)
|
|
36
|
-
from classiq.interface.generator.finance import Finance, FinanceModels, FinancePayoff
|
|
37
36
|
from classiq.interface.generator.function_param_library import FunctionParamLibrary
|
|
38
37
|
from classiq.interface.generator.hadamard_transform import HadamardTransform
|
|
39
38
|
from classiq.interface.generator.hamiltonian_evolution.exponentiation import (
|
|
@@ -106,9 +105,6 @@ function_param_library: FunctionParamLibrary = FunctionParamLibrary(
|
|
|
106
105
|
CyclicShift,
|
|
107
106
|
Modulo,
|
|
108
107
|
TwoDimensionalEntangler,
|
|
109
|
-
Finance,
|
|
110
|
-
FinanceModels,
|
|
111
|
-
FinancePayoff,
|
|
112
108
|
HypercubeEntangler,
|
|
113
109
|
GridEntangler,
|
|
114
110
|
Mcx,
|
|
@@ -144,6 +144,14 @@ class ClassicalArray(ClassicalType):
|
|
|
144
144
|
def has_length(self) -> bool:
|
|
145
145
|
return self.length is not None and self.length.is_evaluated()
|
|
146
146
|
|
|
147
|
+
@property
|
|
148
|
+
def has_constant_length(self) -> bool:
|
|
149
|
+
return (
|
|
150
|
+
self.length is not None
|
|
151
|
+
and self.length.is_evaluated()
|
|
152
|
+
and self.length.is_constant()
|
|
153
|
+
)
|
|
154
|
+
|
|
147
155
|
@property
|
|
148
156
|
def length_value(self) -> int:
|
|
149
157
|
if not self.has_length:
|
|
@@ -101,6 +101,12 @@ class TypeName(ClassicalType, QuantumType):
|
|
|
101
101
|
field_type.is_evaluated for field_type in self.fields.values()
|
|
102
102
|
)
|
|
103
103
|
|
|
104
|
+
@property
|
|
105
|
+
def is_constant(self) -> bool:
|
|
106
|
+
return self.has_fields and all(
|
|
107
|
+
field_type.is_constant for field_type in self.fields.values()
|
|
108
|
+
)
|
|
109
|
+
|
|
104
110
|
@property
|
|
105
111
|
def has_classical_struct_decl(self) -> bool:
|
|
106
112
|
return self._classical_struct_decl is not None
|
|
@@ -57,11 +57,15 @@ EXTRA_TWO_QUBIT_GATES: BasisGates = frozenset(
|
|
|
57
57
|
)
|
|
58
58
|
)
|
|
59
59
|
|
|
60
|
+
NON_UNITARY_GATES: BasisGates = frozenset(("if_else",))
|
|
61
|
+
|
|
60
62
|
TWO_QUBIT_GATES = BASIC_TWO_QUBIT_GATES | EXTRA_TWO_QUBIT_GATES
|
|
61
63
|
|
|
62
64
|
THREE_QUBIT_GATES: BasisGates = frozenset(("ccx", "cswap"))
|
|
63
65
|
DEFAULT_BASIS_GATES: BasisGates = SINGLE_QUBIT_GATES | BASIC_TWO_QUBIT_GATES
|
|
64
|
-
ALL_GATES: BasisGates =
|
|
66
|
+
ALL_GATES: BasisGates = (
|
|
67
|
+
SINGLE_QUBIT_GATES | TWO_QUBIT_GATES | THREE_QUBIT_GATES | NON_UNITARY_GATES
|
|
68
|
+
)
|
|
65
69
|
|
|
66
70
|
ROUTING_TWO_QUBIT_BASIS_GATES: BasisGates = frozenset(
|
|
67
71
|
("cx", "ecr", "rzx", "ryy", "rxx", "rzz", "cy", "cz", "cp", "swap")
|
|
@@ -132,13 +132,6 @@ class FermionMapping(IntEnum):
|
|
|
132
132
|
FAST_BRAVYI_KITAEV = 3
|
|
133
133
|
|
|
134
134
|
|
|
135
|
-
class FinanceFunctionType(IntEnum):
|
|
136
|
-
VAR = 0
|
|
137
|
-
SHORTFALL = 1
|
|
138
|
-
X_SQUARE = 2
|
|
139
|
-
EUROPEAN_CALL_OPTION = 3
|
|
140
|
-
|
|
141
|
-
|
|
142
135
|
class LadderOperator(IntEnum):
|
|
143
136
|
PLUS = 0
|
|
144
137
|
MINUS = 1
|
|
@@ -171,7 +164,6 @@ class QSVMFeatureMapEntanglement(IntEnum):
|
|
|
171
164
|
__all__ = [
|
|
172
165
|
"Element",
|
|
173
166
|
"FermionMapping",
|
|
174
|
-
"FinanceFunctionType",
|
|
175
167
|
"LadderOperator",
|
|
176
168
|
"Optimizer",
|
|
177
169
|
"Pauli",
|
|
@@ -3,6 +3,8 @@ import operator
|
|
|
3
3
|
from collections.abc import Mapping
|
|
4
4
|
from typing import TYPE_CHECKING, Literal
|
|
5
5
|
|
|
6
|
+
import pydantic
|
|
7
|
+
|
|
6
8
|
from classiq.interface.ast_node import ASTNodeType, reset_lists
|
|
7
9
|
from classiq.interface.generator.expressions.expression import Expression
|
|
8
10
|
from classiq.interface.model.handle_binding import ConcreteHandleBinding, HandleBinding
|
|
@@ -18,6 +20,9 @@ class ClassicalIf(QuantumOperation):
|
|
|
18
20
|
condition: Expression
|
|
19
21
|
then: "StatementBlock"
|
|
20
22
|
else_: "StatementBlock"
|
|
23
|
+
_condition_wiring_inouts: dict[str, HandleBinding] = pydantic.PrivateAttr(
|
|
24
|
+
default_factory=dict
|
|
25
|
+
)
|
|
21
26
|
|
|
22
27
|
def _as_back_ref(self: ASTNodeType) -> ASTNodeType:
|
|
23
28
|
return reset_lists(self, ["then", "else_"])
|
|
@@ -40,14 +45,17 @@ class ClassicalIf(QuantumOperation):
|
|
|
40
45
|
|
|
41
46
|
@property
|
|
42
47
|
def wiring_inouts(self) -> Mapping[str, ConcreteHandleBinding]:
|
|
43
|
-
return
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
return (
|
|
49
|
+
functools.reduce(
|
|
50
|
+
operator.ior,
|
|
51
|
+
(
|
|
52
|
+
op.wiring_inouts
|
|
53
|
+
for op in (*self.then, *self.else_)
|
|
54
|
+
if isinstance(op, QuantumOperation)
|
|
55
|
+
),
|
|
56
|
+
dict(),
|
|
57
|
+
)
|
|
58
|
+
| self._condition_wiring_inouts
|
|
51
59
|
)
|
|
52
60
|
|
|
53
61
|
@property
|
|
@@ -44,6 +44,18 @@ class AnonPortDeclaration(Parameter):
|
|
|
44
44
|
raise ClassiqInternalError
|
|
45
45
|
return PortDeclaration(**{**self.__dict__, "name": new_name})
|
|
46
46
|
|
|
47
|
+
@property
|
|
48
|
+
def qmod_type_name(self) -> str:
|
|
49
|
+
prefix = ""
|
|
50
|
+
suffix = ""
|
|
51
|
+
if self.type_modifier in (TypeModifier.Const, TypeModifier.Permutable):
|
|
52
|
+
prefix += f"{self.type_modifier.name}["
|
|
53
|
+
suffix += "]"
|
|
54
|
+
if self.direction != PortDeclarationDirection.Inout:
|
|
55
|
+
prefix += f"{self.direction.name}["
|
|
56
|
+
suffix += "]"
|
|
57
|
+
return f"{prefix}{self.quantum_type.qmod_type_name}{suffix}"
|
|
58
|
+
|
|
47
59
|
|
|
48
60
|
class PortDeclaration(AnonPortDeclaration):
|
|
49
61
|
name: str
|
|
@@ -190,6 +190,18 @@ class AnonQuantumOperandDeclaration(AnonQuantumFunctionDeclaration):
|
|
|
190
190
|
def is_generative(self) -> bool:
|
|
191
191
|
return self._is_generative
|
|
192
192
|
|
|
193
|
+
@property
|
|
194
|
+
def qmod_type_name(self) -> str:
|
|
195
|
+
if self.is_list:
|
|
196
|
+
type_name = "QCallableList"
|
|
197
|
+
else:
|
|
198
|
+
type_name = "QCallable"
|
|
199
|
+
if len(self.positional_arg_declarations) == 0:
|
|
200
|
+
params = ""
|
|
201
|
+
else:
|
|
202
|
+
params = f"[{', '.join(param.qmod_type_name for param in self.positional_arg_declarations)}]"
|
|
203
|
+
return f"{type_name}{params}"
|
|
204
|
+
|
|
193
205
|
|
|
194
206
|
AnonQuantumFunctionDeclaration.model_rebuild()
|
|
195
207
|
|
|
@@ -84,6 +84,10 @@ class QuantumType(HashableASTNode):
|
|
|
84
84
|
def is_evaluated(self) -> bool:
|
|
85
85
|
raise NotImplementedError
|
|
86
86
|
|
|
87
|
+
@property
|
|
88
|
+
def is_constant(self) -> bool:
|
|
89
|
+
raise NotImplementedError
|
|
90
|
+
|
|
87
91
|
@property
|
|
88
92
|
def expressions(self) -> list[Expression]:
|
|
89
93
|
return []
|
|
@@ -109,6 +113,9 @@ class QuantumScalar(QuantumType):
|
|
|
109
113
|
def fraction_digits_value(self) -> int:
|
|
110
114
|
raise NotImplementedError
|
|
111
115
|
|
|
116
|
+
def get_bounds(self) -> Optional[tuple[float, float]]:
|
|
117
|
+
return None
|
|
118
|
+
|
|
112
119
|
def get_effective_bounds(
|
|
113
120
|
self, machine_precision: Optional[int] = None
|
|
114
121
|
) -> tuple[float, float]:
|
|
@@ -154,6 +161,10 @@ class QuantumBit(QuantumScalar):
|
|
|
154
161
|
def is_evaluated(self) -> bool:
|
|
155
162
|
return True
|
|
156
163
|
|
|
164
|
+
@property
|
|
165
|
+
def is_constant(self) -> bool:
|
|
166
|
+
return True
|
|
167
|
+
|
|
157
168
|
@property
|
|
158
169
|
def has_sign(self) -> bool:
|
|
159
170
|
return True
|
|
@@ -257,6 +268,15 @@ class QuantumBitvector(QuantumType):
|
|
|
257
268
|
and self.element_type.is_evaluated
|
|
258
269
|
)
|
|
259
270
|
|
|
271
|
+
@property
|
|
272
|
+
def is_constant(self) -> bool:
|
|
273
|
+
return (
|
|
274
|
+
self.length is not None
|
|
275
|
+
and self.length.is_evaluated()
|
|
276
|
+
and self.length.is_constant()
|
|
277
|
+
and self.element_type.is_constant
|
|
278
|
+
)
|
|
279
|
+
|
|
260
280
|
@property
|
|
261
281
|
def expressions(self) -> list[Expression]:
|
|
262
282
|
exprs = self.element_type.expressions
|
|
@@ -311,6 +331,14 @@ class QuantumNumeric(QuantumScalar):
|
|
|
311
331
|
def has_sign(self) -> bool:
|
|
312
332
|
return self.is_signed is not None
|
|
313
333
|
|
|
334
|
+
@property
|
|
335
|
+
def has_constant_sign(self) -> bool:
|
|
336
|
+
return (
|
|
337
|
+
self.is_signed is not None
|
|
338
|
+
and self.is_signed.is_evaluated()
|
|
339
|
+
and self.is_signed.is_constant()
|
|
340
|
+
)
|
|
341
|
+
|
|
314
342
|
@property
|
|
315
343
|
def sign_value(self) -> bool:
|
|
316
344
|
return False if self.is_signed is None else self.is_signed.to_bool_value()
|
|
@@ -319,6 +347,14 @@ class QuantumNumeric(QuantumScalar):
|
|
|
319
347
|
def has_fraction_digits(self) -> bool:
|
|
320
348
|
return self.fraction_digits is not None
|
|
321
349
|
|
|
350
|
+
@property
|
|
351
|
+
def has_constant_fraction_digits(self) -> bool:
|
|
352
|
+
return (
|
|
353
|
+
self.fraction_digits is not None
|
|
354
|
+
and self.fraction_digits.is_evaluated()
|
|
355
|
+
and self.fraction_digits.is_constant()
|
|
356
|
+
)
|
|
357
|
+
|
|
322
358
|
@property
|
|
323
359
|
def fraction_digits_value(self) -> int:
|
|
324
360
|
return (
|
|
@@ -388,6 +424,26 @@ class QuantumNumeric(QuantumScalar):
|
|
|
388
424
|
self.fraction_digits is not None and not self.fraction_digits.is_evaluated()
|
|
389
425
|
)
|
|
390
426
|
|
|
427
|
+
@property
|
|
428
|
+
def is_constant(self) -> bool:
|
|
429
|
+
if (
|
|
430
|
+
self.size is None
|
|
431
|
+
or not self.size.is_evaluated()
|
|
432
|
+
or not self.size.is_constant()
|
|
433
|
+
):
|
|
434
|
+
return False
|
|
435
|
+
if self.is_signed is not None and (
|
|
436
|
+
not self.is_signed.is_evaluated() or not self.is_signed.is_constant()
|
|
437
|
+
):
|
|
438
|
+
return False
|
|
439
|
+
return not (
|
|
440
|
+
self.fraction_digits is not None
|
|
441
|
+
and (
|
|
442
|
+
not self.fraction_digits.is_evaluated()
|
|
443
|
+
or not self.fraction_digits.is_constant()
|
|
444
|
+
)
|
|
445
|
+
)
|
|
446
|
+
|
|
391
447
|
@property
|
|
392
448
|
def expressions(self) -> list[Expression]:
|
|
393
449
|
exprs = []
|
|
@@ -141,24 +141,10 @@ class ASTToQMODCode:
|
|
|
141
141
|
if len(node.args) != 2:
|
|
142
142
|
raise PrettyPrinterError("Error parsing array access.")
|
|
143
143
|
return f"{self.ast_to_code(node.args[0])}[{self.ast_to_code(node.args[1])}]"
|
|
144
|
-
elif len(node.keywords) > 0:
|
|
145
|
-
# struct instance
|
|
146
|
-
keywords = node.keywords
|
|
147
|
-
initializer_list = self.indent_items(
|
|
148
|
-
lambda: [
|
|
149
|
-
f"{keyword.arg}={self._cleaned_ast_to_code(keyword.value)}"
|
|
150
|
-
for keyword in keywords
|
|
151
|
-
if keyword.arg is not None
|
|
152
|
-
]
|
|
153
|
-
)
|
|
154
|
-
return f"{func} {{{initializer_list}}}"
|
|
155
144
|
else:
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
for kwarg in node.keywords
|
|
160
|
-
]
|
|
161
|
-
return "{}({})".format(func, ", ".join(args + kwargs))
|
|
145
|
+
return "{}({})".format(
|
|
146
|
+
func, ", ".join(self._cleaned_ast_to_code(arg) for arg in node.args)
|
|
147
|
+
)
|
|
162
148
|
elif isinstance(node, ast.Expr):
|
|
163
149
|
return self._cleaned_ast_to_code(node.value)
|
|
164
150
|
else:
|
|
@@ -78,7 +78,7 @@ class AllocateEmitter(Emitter[Allocate]):
|
|
|
78
78
|
target: QuantumSymbol,
|
|
79
79
|
op_update_dict: dict[str, Expression],
|
|
80
80
|
) -> None:
|
|
81
|
-
if target.quantum_type.
|
|
81
|
+
if target.quantum_type.has_size_in_bits:
|
|
82
82
|
expr = str(target.quantum_type.size_in_bits)
|
|
83
83
|
elif self._allow_symbolic_attrs:
|
|
84
84
|
expr = f"{target.handle}.size"
|
|
@@ -19,11 +19,5 @@ class HandleEvaluator(Emitter[QuantumOperation]):
|
|
|
19
19
|
if not isinstance(handle, HandleBinding):
|
|
20
20
|
return False
|
|
21
21
|
evaluated_handle = self._interpreter.evaluate(handle).value.handle.collapse()
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
op = op.model_copy(
|
|
25
|
-
update={self._handle_name: evaluated_handle, "back_ref": op.uuid}
|
|
26
|
-
)
|
|
27
|
-
self._interpreter.add_to_debug_info(op)
|
|
28
|
-
self._interpreter.emit(op)
|
|
29
|
-
return True
|
|
22
|
+
setattr(op, self._handle_name, evaluated_handle)
|
|
23
|
+
return False
|
|
@@ -3,7 +3,7 @@ from typing import Literal
|
|
|
3
3
|
import numpy as np
|
|
4
4
|
|
|
5
5
|
from classiq.open_library.functions.state_preparation import (
|
|
6
|
-
|
|
6
|
+
apply_phase_table,
|
|
7
7
|
)
|
|
8
8
|
from classiq.open_library.functions.utility_functions import switch
|
|
9
9
|
from classiq.qmod.builtins.functions import IDENTITY, X, Y, Z, inplace_prepare_state
|
|
@@ -73,7 +73,7 @@ def lcu(
|
|
|
73
73
|
iteration=lambda i: control(block == i, lambda: unitaries[i]()),
|
|
74
74
|
),
|
|
75
75
|
# TODO: replace to sparse constant phase
|
|
76
|
-
|
|
76
|
+
apply_phase_table(phases, block),
|
|
77
77
|
],
|
|
78
78
|
)
|
|
79
79
|
|
|
@@ -13,8 +13,8 @@ from classiq.open_library.functions.utility_functions import (
|
|
|
13
13
|
from classiq.qmod.builtins.functions import (
|
|
14
14
|
CX,
|
|
15
15
|
IDENTITY,
|
|
16
|
+
PHASE,
|
|
16
17
|
RY,
|
|
17
|
-
RZ,
|
|
18
18
|
H,
|
|
19
19
|
X,
|
|
20
20
|
inplace_prepare_amplitudes,
|
|
@@ -324,7 +324,7 @@ def _classical_hadamard_transform(arr: list[float]) -> np.ndarray:
|
|
|
324
324
|
|
|
325
325
|
|
|
326
326
|
@qfunc
|
|
327
|
-
def
|
|
327
|
+
def apply_phase_table(
|
|
328
328
|
phases: list[float],
|
|
329
329
|
target: QArray[QBit, Literal["log(get_field(phases, 'len'), 2)"]],
|
|
330
330
|
) -> None:
|
|
@@ -333,10 +333,10 @@ def _load_phases(
|
|
|
333
333
|
for i in range(1, len(alphas) - 1):
|
|
334
334
|
gray = _graycode(i)
|
|
335
335
|
next_gray = _graycode(i + 1)
|
|
336
|
-
|
|
336
|
+
PHASE(alphas[gray], target[_msb(gray)])
|
|
337
337
|
CX(target[_control_qubit(i)], target[_msb(next_gray)])
|
|
338
338
|
|
|
339
|
-
|
|
339
|
+
PHASE(alphas[_graycode(len(phases) - 1)], target[target.len - 1])
|
|
340
340
|
|
|
341
341
|
|
|
342
342
|
@qfunc
|
|
@@ -358,7 +358,7 @@ def inplace_prepare_complex_amplitudes(
|
|
|
358
358
|
target: The quantum variable to act upon.
|
|
359
359
|
"""
|
|
360
360
|
inplace_prepare_amplitudes(magnitudes, 0, target)
|
|
361
|
-
|
|
361
|
+
apply_phase_table(phases, target)
|
|
362
362
|
|
|
363
363
|
|
|
364
364
|
@qfunc
|
|
@@ -469,3 +469,45 @@ def prepare_basis_state(state: list[bool], arr: Output[QArray]) -> None:
|
|
|
469
469
|
for idx, value in enumerate(state):
|
|
470
470
|
if value:
|
|
471
471
|
X(arr[idx])
|
|
472
|
+
|
|
473
|
+
|
|
474
|
+
def linear_hadamard_walsh_coefficients(n: int) -> np.ndarray:
|
|
475
|
+
coeffs = np.zeros(n + 1)
|
|
476
|
+
coeffs[0] = 2 ** (n / 2) * ((2**n - 1) / 2)
|
|
477
|
+
for k in range(1, n + 1):
|
|
478
|
+
coeffs[k] = -(2 ** (k - 1 + n / 2) / 2)
|
|
479
|
+
return coeffs / np.linalg.norm(coeffs)
|
|
480
|
+
|
|
481
|
+
|
|
482
|
+
@qfunc
|
|
483
|
+
def _zero_ctrl_rot(ctrl: QNum, target: QBit, theta: CReal) -> None:
|
|
484
|
+
control(ctrl == 0, lambda: RY(theta, target))
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
@qfunc
|
|
488
|
+
def prepare_linear_amplitudes(x: QArray) -> None:
|
|
489
|
+
""" "
|
|
490
|
+
[Qmod Classiq-library function]
|
|
491
|
+
|
|
492
|
+
Initializes a quantum variable in a state with linear amplitudes:
|
|
493
|
+
$$|\\psi\rangle = \frac{1}{Z}\\sum_{x=0}^{2^n-1}{x|x\rangle}$$
|
|
494
|
+
Where $Z$ is a normalization constant.
|
|
495
|
+
|
|
496
|
+
Based on the paper https://quantum-journal.org/papers/q-2024-03-21-1297/pdf/
|
|
497
|
+
|
|
498
|
+
Args:
|
|
499
|
+
x: The quantum register to prepare.
|
|
500
|
+
"""
|
|
501
|
+
coeffs = linear_hadamard_walsh_coefficients(x.size) # type: ignore[arg-type]
|
|
502
|
+
thetas = np.zeros(x.size + 1) # type: ignore[arg-type]
|
|
503
|
+
for i in range(x.size): # type: ignore[arg-type]
|
|
504
|
+
thetas[i] = 2 * np.arcsin(
|
|
505
|
+
coeffs[i + 1] / np.sqrt(1 - np.linalg.norm(coeffs[1 : i + 1]) ** 2)
|
|
506
|
+
)
|
|
507
|
+
for k in range(x.len):
|
|
508
|
+
if k == 0:
|
|
509
|
+
RY(thetas[k], x[k])
|
|
510
|
+
else:
|
|
511
|
+
_zero_ctrl_rot(x[0:k], x[k], thetas[k])
|
|
512
|
+
|
|
513
|
+
hadamard_transform(x)
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
from classiq.interface.finance.function_input import FinanceFunctionInput
|
|
2
|
-
|
|
3
1
|
from .classical_execution_primitives import * # noqa: F403
|
|
4
2
|
from .classical_execution_primitives import (
|
|
5
3
|
__all__ as _builtin_classical_execution_primitives,
|
|
@@ -17,7 +15,6 @@ from .operations import __all__ as _builtin_operations
|
|
|
17
15
|
from .structs import * # noqa: F403
|
|
18
16
|
from .structs import __all__ as _builtin_structs
|
|
19
17
|
|
|
20
|
-
FinanceFunctionInput.model_rebuild()
|
|
21
18
|
BUILTIN_CONSTANTS = [
|
|
22
19
|
constant._get_constant_node()
|
|
23
20
|
for constant in [
|
|
@@ -54,38 +54,10 @@ def hypercube_entangler_graph(
|
|
|
54
54
|
)
|
|
55
55
|
|
|
56
56
|
|
|
57
|
-
def gaussian_finance_post_process(
|
|
58
|
-
finance_model: GaussianModel,
|
|
59
|
-
estimation_method: FinanceFunction,
|
|
60
|
-
probability: CReal,
|
|
61
|
-
) -> CReal:
|
|
62
|
-
return symbolic_function(
|
|
63
|
-
finance_model,
|
|
64
|
-
estimation_method,
|
|
65
|
-
probability,
|
|
66
|
-
return_type=CReal, # type:ignore[type-abstract]
|
|
67
|
-
)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
def log_normal_finance_post_process(
|
|
71
|
-
finance_model: LogNormalModel,
|
|
72
|
-
estimation_method: FinanceFunction,
|
|
73
|
-
probability: CReal,
|
|
74
|
-
) -> CReal:
|
|
75
|
-
return symbolic_function(
|
|
76
|
-
finance_model,
|
|
77
|
-
estimation_method,
|
|
78
|
-
probability,
|
|
79
|
-
return_type=CReal, # type:ignore[type-abstract]
|
|
80
|
-
)
|
|
81
|
-
|
|
82
|
-
|
|
83
57
|
__all__ = [
|
|
84
58
|
"qft_const_adder_phase",
|
|
85
59
|
"fock_hamiltonian_problem_to_hamiltonian",
|
|
86
60
|
"molecule_problem_to_hamiltonian",
|
|
87
61
|
"grid_entangler_graph",
|
|
88
62
|
"hypercube_entangler_graph",
|
|
89
|
-
"gaussian_finance_post_process",
|
|
90
|
-
"log_normal_finance_post_process",
|
|
91
63
|
]
|