classiq 0.73.0__py3-none-any.whl → 0.75.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/client.py +9 -10
- classiq/analyzer/show_interactive_hack.py +1 -1
- classiq/applications/qnn/qlayer.py +9 -0
- classiq/interface/_version.py +1 -1
- classiq/interface/ast_node.py +5 -2
- classiq/interface/compression_utils.py +31 -0
- classiq/interface/debug_info/debug_info.py +2 -11
- classiq/interface/generator/expressions/proxies/classical/classical_array_proxy.py +5 -5
- classiq/interface/generator/expressions/proxies/classical/utils.py +2 -2
- classiq/interface/generator/functions/classical_type.py +30 -0
- classiq/interface/generator/functions/type_name.py +25 -3
- classiq/interface/generator/generated_circuit_data.py +11 -25
- classiq/interface/generator/quantum_program.py +14 -0
- classiq/interface/generator/synthesis_metadata/synthesis_execution_data.py +10 -13
- classiq/interface/helpers/versioned_model.py +12 -0
- classiq/interface/ide/visual_model.py +4 -2
- classiq/interface/interface_version.py +1 -1
- classiq/interface/model/handle_binding.py +12 -0
- classiq/interface/model/quantum_lambda_function.py +14 -0
- classiq/interface/model/statement_block.py +9 -1
- classiq/interface/model/within_apply_operation.py +12 -0
- classiq/model_expansions/atomic_expression_functions_defs.py +24 -8
- classiq/model_expansions/capturing/captured_vars.py +28 -6
- classiq/model_expansions/closure.py +13 -0
- classiq/model_expansions/evaluators/argument_types.py +6 -5
- classiq/model_expansions/evaluators/type_type_match.py +2 -1
- classiq/model_expansions/generative_functions.py +14 -8
- classiq/model_expansions/interpreters/base_interpreter.py +10 -13
- classiq/model_expansions/interpreters/frontend_generative_interpreter.py +21 -0
- classiq/model_expansions/interpreters/generative_interpreter.py +13 -5
- classiq/model_expansions/quantum_operations/allocate.py +22 -11
- classiq/model_expansions/quantum_operations/assignment_result_processor.py +2 -0
- classiq/model_expansions/quantum_operations/call_emitter.py +5 -10
- classiq/model_expansions/quantum_operations/emitter.py +1 -5
- classiq/model_expansions/quantum_operations/expression_evaluator.py +1 -0
- classiq/model_expansions/quantum_operations/handle_evaluator.py +1 -0
- classiq/model_expansions/transformers/model_renamer.py +3 -1
- classiq/model_expansions/visitors/symbolic_param_inference.py +197 -0
- classiq/open_library/functions/__init__.py +2 -0
- classiq/open_library/functions/amplitude_amplification.py +5 -3
- classiq/open_library/functions/state_preparation.py +95 -2
- classiq/qmod/model_state_container.py +11 -8
- classiq/qmod/qmod_variable.py +23 -1
- classiq/qmod/quantum_function.py +1 -9
- classiq/qmod/symbolic_expr.py +8 -2
- classiq/qmod/write_qmod.py +5 -1
- {classiq-0.73.0.dist-info → classiq-0.75.0.dist-info}/METADATA +2 -1
- {classiq-0.73.0.dist-info → classiq-0.75.0.dist-info}/RECORD +49 -47
- {classiq-0.73.0.dist-info → classiq-0.75.0.dist-info}/WHEEL +1 -1
@@ -0,0 +1,197 @@
|
|
1
|
+
import ast
|
2
|
+
from collections.abc import Iterator, Mapping, Sequence
|
3
|
+
from contextlib import contextmanager
|
4
|
+
from itertools import chain, zip_longest
|
5
|
+
from typing import Optional, cast
|
6
|
+
|
7
|
+
from classiq.interface.generator.expressions.atomic_expression_functions import (
|
8
|
+
CLASSICAL_ATTRIBUTES,
|
9
|
+
)
|
10
|
+
from classiq.interface.generator.expressions.expression import Expression
|
11
|
+
from classiq.interface.generator.functions.classical_type import ClassicalType
|
12
|
+
from classiq.interface.generator.functions.type_name import TypeName
|
13
|
+
from classiq.interface.helpers.pydantic_model_helpers import nameables_to_dict
|
14
|
+
from classiq.interface.model.classical_parameter_declaration import (
|
15
|
+
AnonClassicalParameterDeclaration,
|
16
|
+
)
|
17
|
+
from classiq.interface.model.handle_binding import FieldHandleBinding, HandleBinding
|
18
|
+
from classiq.interface.model.model_visitor import ModelVisitor
|
19
|
+
from classiq.interface.model.native_function_definition import NativeFunctionDefinition
|
20
|
+
from classiq.interface.model.quantum_function_call import ArgValue, QuantumFunctionCall
|
21
|
+
from classiq.interface.model.quantum_function_declaration import (
|
22
|
+
AnonPositionalArg,
|
23
|
+
AnonQuantumFunctionDeclaration,
|
24
|
+
AnonQuantumOperandDeclaration,
|
25
|
+
NamedParamsQuantumFunctionDeclaration,
|
26
|
+
QuantumOperandDeclaration,
|
27
|
+
)
|
28
|
+
from classiq.interface.model.quantum_lambda_function import (
|
29
|
+
OperandIdentifier,
|
30
|
+
QuantumLambdaFunction,
|
31
|
+
)
|
32
|
+
|
33
|
+
from classiq.model_expansions.visitors.variable_references import VarRefCollector
|
34
|
+
|
35
|
+
|
36
|
+
def _get_expressions(arg: ArgValue) -> list[Expression]:
|
37
|
+
if isinstance(arg, Expression):
|
38
|
+
return [arg]
|
39
|
+
if isinstance(arg, HandleBinding):
|
40
|
+
return arg.expressions()
|
41
|
+
if isinstance(arg, OperandIdentifier):
|
42
|
+
return [arg.index]
|
43
|
+
if isinstance(arg, list):
|
44
|
+
return list(chain.from_iterable(_get_expressions(item) for item in arg))
|
45
|
+
return []
|
46
|
+
|
47
|
+
|
48
|
+
def _get_param_expressions(param: AnonPositionalArg) -> list[Expression]:
|
49
|
+
if isinstance(param, AnonClassicalParameterDeclaration):
|
50
|
+
return param.classical_type.expressions
|
51
|
+
if isinstance(param, AnonQuantumOperandDeclaration):
|
52
|
+
return list(
|
53
|
+
chain.from_iterable(
|
54
|
+
_get_param_expressions(nested_param)
|
55
|
+
for nested_param in param.positional_arg_declarations
|
56
|
+
)
|
57
|
+
)
|
58
|
+
return param.quantum_type.expressions
|
59
|
+
|
60
|
+
|
61
|
+
class SymbolicParamInference(ModelVisitor):
|
62
|
+
def __init__(
|
63
|
+
self,
|
64
|
+
functions: list[NativeFunctionDefinition],
|
65
|
+
additional_signatures: (
|
66
|
+
list[NamedParamsQuantumFunctionDeclaration] | None
|
67
|
+
) = None,
|
68
|
+
) -> None:
|
69
|
+
self._functions = nameables_to_dict(functions)
|
70
|
+
self._additional_signatures = (
|
71
|
+
{}
|
72
|
+
if additional_signatures is None
|
73
|
+
else nameables_to_dict(additional_signatures)
|
74
|
+
)
|
75
|
+
self._inferred_funcs: set[str] = set()
|
76
|
+
self._call_stack: list[str] = []
|
77
|
+
self._scope: Mapping[str, ClassicalType] = {}
|
78
|
+
self._scope_operands: dict[str, QuantumOperandDeclaration] = {}
|
79
|
+
|
80
|
+
def infer(self) -> None:
|
81
|
+
for func in self._functions.values():
|
82
|
+
self._infer_func_params(func)
|
83
|
+
|
84
|
+
def _is_recursive_call(self, func: str) -> bool:
|
85
|
+
return func in self._call_stack
|
86
|
+
|
87
|
+
@contextmanager
|
88
|
+
def function_context(
|
89
|
+
self,
|
90
|
+
func_name: Optional[str],
|
91
|
+
scope: Mapping[str, ClassicalType],
|
92
|
+
scope_operands: dict[str, QuantumOperandDeclaration],
|
93
|
+
) -> Iterator[None]:
|
94
|
+
if func_name is not None:
|
95
|
+
self._call_stack.append(func_name)
|
96
|
+
prev_scope = self._scope
|
97
|
+
self._scope = scope
|
98
|
+
prev_scope_ops = self._scope_operands
|
99
|
+
self._scope_operands = scope_operands
|
100
|
+
yield
|
101
|
+
self._scope = prev_scope
|
102
|
+
self._scope_operands = prev_scope_ops
|
103
|
+
if func_name is not None:
|
104
|
+
self._call_stack.pop()
|
105
|
+
|
106
|
+
def _infer_func_params(self, func: NativeFunctionDefinition) -> None:
|
107
|
+
if func.name in self._inferred_funcs:
|
108
|
+
return
|
109
|
+
scope = {param.name: param.classical_type for param in func.param_decls}
|
110
|
+
scope_operands = func.operand_declarations_dict
|
111
|
+
with self.function_context(func.name, scope, scope_operands):
|
112
|
+
for param in func.positional_arg_declarations:
|
113
|
+
for expr in _get_param_expressions(param):
|
114
|
+
self._process_compile_time_expression(expr.expr)
|
115
|
+
self._set_enums_generative(func)
|
116
|
+
self.visit(func.body)
|
117
|
+
self._inferred_funcs.add(func.name)
|
118
|
+
|
119
|
+
def _set_enums_generative(self, decl: AnonQuantumFunctionDeclaration) -> None:
|
120
|
+
for param in decl.positional_arg_declarations:
|
121
|
+
if (
|
122
|
+
isinstance(param, AnonClassicalParameterDeclaration)
|
123
|
+
and param.name is not None
|
124
|
+
and isinstance(param.classical_type, TypeName)
|
125
|
+
and param.classical_type.is_enum
|
126
|
+
):
|
127
|
+
self._scope[param.name].set_generative()
|
128
|
+
|
129
|
+
def visit_QuantumLambdaFunction(self, func: QuantumLambdaFunction) -> None:
|
130
|
+
func.set_op_decl(func.func_decl.model_copy(deep=True))
|
131
|
+
scope = dict(self._scope) | {
|
132
|
+
cast(str, param.name): param.classical_type
|
133
|
+
for param in func.named_func_decl.param_decls
|
134
|
+
}
|
135
|
+
scope_operands = self._scope_operands | nameables_to_dict(
|
136
|
+
cast(
|
137
|
+
Sequence[QuantumOperandDeclaration],
|
138
|
+
func.named_func_decl.operand_declarations,
|
139
|
+
)
|
140
|
+
)
|
141
|
+
with self.function_context(None, scope, scope_operands):
|
142
|
+
self._set_enums_generative(func.named_func_decl)
|
143
|
+
self.visit(func.body)
|
144
|
+
|
145
|
+
def visit_QuantumFunctionCall(self, call: QuantumFunctionCall) -> None:
|
146
|
+
self._process_compile_time_expressions(call.function)
|
147
|
+
name = call.func_name
|
148
|
+
if self._is_recursive_call(name):
|
149
|
+
return # Recursion is not fully supported
|
150
|
+
params = self._get_params(call)
|
151
|
+
for param, arg in zip_longest(params, call.positional_args):
|
152
|
+
if (
|
153
|
+
not isinstance(param, AnonClassicalParameterDeclaration)
|
154
|
+
or param.classical_type.is_generative
|
155
|
+
):
|
156
|
+
self._process_compile_time_expressions(arg)
|
157
|
+
else:
|
158
|
+
for expr in _get_expressions(arg):
|
159
|
+
self._process_nested_compile_time_expression(expr.expr)
|
160
|
+
self.generic_visit(call)
|
161
|
+
|
162
|
+
def _get_params(self, call: QuantumFunctionCall) -> Sequence[AnonPositionalArg]:
|
163
|
+
name = call.func_name
|
164
|
+
if name in self._scope_operands:
|
165
|
+
return self._scope_operands[name].positional_arg_declarations
|
166
|
+
elif name in self._functions:
|
167
|
+
func = self._functions[name]
|
168
|
+
self._infer_func_params(func)
|
169
|
+
return func.positional_arg_declarations
|
170
|
+
elif name in self._additional_signatures:
|
171
|
+
return self._additional_signatures[name].positional_arg_declarations
|
172
|
+
return call.func_decl.positional_arg_declarations
|
173
|
+
|
174
|
+
def _process_compile_time_expressions(self, arg: ArgValue) -> None:
|
175
|
+
for expr in _get_expressions(arg):
|
176
|
+
self._process_compile_time_expression(expr.expr)
|
177
|
+
|
178
|
+
def _process_compile_time_expression(self, expr: str) -> None:
|
179
|
+
vrc = VarRefCollector(
|
180
|
+
ignore_duplicated_handles=True, ignore_sympy_symbols=True, unevaluated=True
|
181
|
+
)
|
182
|
+
vrc.visit(ast.parse(expr))
|
183
|
+
for handle in vrc.var_handles:
|
184
|
+
if handle.name in self._scope and (
|
185
|
+
not isinstance(handle, FieldHandleBinding)
|
186
|
+
or handle.field not in CLASSICAL_ATTRIBUTES
|
187
|
+
):
|
188
|
+
self._scope[handle.name].set_generative()
|
189
|
+
|
190
|
+
def _process_nested_compile_time_expression(self, expr: str) -> None:
|
191
|
+
vrc = VarRefCollector(
|
192
|
+
ignore_duplicated_handles=True, ignore_sympy_symbols=True, unevaluated=True
|
193
|
+
)
|
194
|
+
vrc.visit(ast.parse(expr))
|
195
|
+
for handle in vrc.var_handles:
|
196
|
+
for nested_expr in handle.expressions():
|
197
|
+
self._process_compile_time_expression(nested_expr.expr)
|
@@ -98,6 +98,7 @@ __all__ = [
|
|
98
98
|
"grover_search",
|
99
99
|
"hadamard_transform",
|
100
100
|
"inplace_c_modular_multiply",
|
101
|
+
"inplace_prepare_complex_amplitudes",
|
101
102
|
"inplace_prepare_int",
|
102
103
|
"linear_pauli_rotations",
|
103
104
|
"modular_exp",
|
@@ -105,6 +106,7 @@ __all__ = [
|
|
105
106
|
"multiswap",
|
106
107
|
"phase_oracle",
|
107
108
|
"prepare_bell_state",
|
109
|
+
"prepare_complex_amplitudes",
|
108
110
|
"prepare_exponential_state",
|
109
111
|
"prepare_ghz_state",
|
110
112
|
"prepare_int",
|
@@ -1,3 +1,5 @@
|
|
1
|
+
import numpy as np
|
2
|
+
|
1
3
|
from classiq.open_library.functions.grover import grover_operator
|
2
4
|
from classiq.qmod.builtins.functions.standard_gates import RY
|
3
5
|
from classiq.qmod.builtins.operations import (
|
@@ -11,7 +13,7 @@ from classiq.qmod.cparam import CInt, CReal
|
|
11
13
|
from classiq.qmod.qfunc import qfunc
|
12
14
|
from classiq.qmod.qmod_variable import QArray, QBit
|
13
15
|
from classiq.qmod.quantum_callable import QCallable
|
14
|
-
from classiq.qmod.symbolic import acos, asin, ceiling,
|
16
|
+
from classiq.qmod.symbolic import acos, asin, ceiling, sin
|
15
17
|
|
16
18
|
|
17
19
|
@qfunc
|
@@ -67,8 +69,8 @@ def exact_amplitude_amplification(
|
|
67
69
|
packed_vars: The variable that holds the state to be amplified. Assumed to be in the zero state at the beginning of the algorithm.
|
68
70
|
"""
|
69
71
|
aux = QBit()
|
70
|
-
k = ceiling((pi / (4 * asin(amplitude))) - 0.5)
|
71
|
-
theta = pi / (4 * k + 2)
|
72
|
+
k = ceiling((np.pi / (4 * asin(amplitude))) - 0.5)
|
73
|
+
theta = np.pi / (4 * k + 2)
|
72
74
|
rot_phase = 2 * acos(sin(theta) / amplitude)
|
73
75
|
|
74
76
|
extended_qvars: QArray = QArray()
|
@@ -1,12 +1,23 @@
|
|
1
1
|
import warnings
|
2
2
|
from typing import Literal
|
3
3
|
|
4
|
+
import numpy as np
|
5
|
+
import sympy
|
6
|
+
|
4
7
|
from classiq.interface.exceptions import ClassiqDeprecationWarning
|
5
8
|
|
6
9
|
from classiq.open_library.functions.utility_functions import hadamard_transform
|
7
|
-
from classiq.qmod.builtins.functions
|
10
|
+
from classiq.qmod.builtins.functions import (
|
11
|
+
CX,
|
12
|
+
IDENTITY,
|
13
|
+
RY,
|
14
|
+
RZ,
|
15
|
+
H,
|
16
|
+
X,
|
17
|
+
inplace_prepare_amplitudes,
|
18
|
+
)
|
8
19
|
from classiq.qmod.builtins.operations import allocate, control, if_, inplace_add, repeat
|
9
|
-
from classiq.qmod.cparam import CBool, CInt
|
20
|
+
from classiq.qmod.cparam import CArray, CBool, CInt, CReal
|
10
21
|
from classiq.qmod.qfunc import qfunc
|
11
22
|
from classiq.qmod.qmod_variable import Output, QArray, QBit, QNum
|
12
23
|
from classiq.qmod.symbolic import (
|
@@ -298,3 +309,85 @@ def prepare_int(
|
|
298
309
|
stacklevel=1,
|
299
310
|
)
|
300
311
|
out |= value
|
312
|
+
|
313
|
+
|
314
|
+
def _control_qubit(i: int) -> int:
|
315
|
+
if _msb(_graycode(i)) < _msb(_graycode(i + 1)):
|
316
|
+
return (_graycode(i) & _graycode(i + 1)).bit_length() - 1
|
317
|
+
return (_graycode(i) ^ _graycode(i + 1)).bit_length() - 1
|
318
|
+
|
319
|
+
|
320
|
+
def _graycode(i: int) -> int:
|
321
|
+
return i ^ (i >> 1)
|
322
|
+
|
323
|
+
|
324
|
+
def _msb(x: int) -> int:
|
325
|
+
"""
|
326
|
+
largest non zero bit
|
327
|
+
"""
|
328
|
+
if x == 0:
|
329
|
+
return 0
|
330
|
+
return x.bit_length() - 1
|
331
|
+
|
332
|
+
|
333
|
+
def _classical_hadamard_transform(arr: list[float]) -> np.ndarray:
|
334
|
+
return 1 / np.sqrt(len(arr)) * np.array(sympy.fwht(np.array(arr)))
|
335
|
+
|
336
|
+
|
337
|
+
@qfunc(generative=True)
|
338
|
+
def _load_phases(
|
339
|
+
phases: list[float],
|
340
|
+
target: QArray[QBit, Literal["log(get_field(phases, 'len'), 2)"]],
|
341
|
+
) -> None:
|
342
|
+
alphas = -2 * _classical_hadamard_transform(phases) / np.sqrt(len(phases))
|
343
|
+
|
344
|
+
for i in range(1, len(alphas) - 1):
|
345
|
+
gray = _graycode(i)
|
346
|
+
next_gray = _graycode(i + 1)
|
347
|
+
RZ(alphas[gray], target[_msb(gray)])
|
348
|
+
CX(target[_control_qubit(i)], target[_msb(next_gray)])
|
349
|
+
|
350
|
+
RZ(alphas[_graycode(len(phases) - 1)], target[target.len - 1])
|
351
|
+
|
352
|
+
|
353
|
+
@qfunc
|
354
|
+
def inplace_prepare_complex_amplitudes(
|
355
|
+
magnitudes: CArray[CReal],
|
356
|
+
phases: CArray[CReal],
|
357
|
+
target: QArray[QBit, Literal["log(get_field(magnitudes, 'len'), 2)"]],
|
358
|
+
) -> None:
|
359
|
+
"""
|
360
|
+
|
361
|
+
[Qmod Classiq-library function]
|
362
|
+
|
363
|
+
Prepares a quantum state with amplitudes and phases for each state according to the given parameters, in polar representation.
|
364
|
+
Expects to act on an initialized zero state $|0\\rangle$.
|
365
|
+
|
366
|
+
Args:
|
367
|
+
magnitudes: Absolute values of the state amplitudes.
|
368
|
+
phases: phases of the state amplitudes. should be of the same size as `amplitudes`.
|
369
|
+
target: The quantum variable to act upon.
|
370
|
+
"""
|
371
|
+
inplace_prepare_amplitudes(magnitudes, 0, target)
|
372
|
+
_load_phases(phases, target)
|
373
|
+
|
374
|
+
|
375
|
+
@qfunc
|
376
|
+
def prepare_complex_amplitudes(
|
377
|
+
magnitudes: CArray[CReal],
|
378
|
+
phases: CArray[CReal],
|
379
|
+
out: Output[QArray[QBit, Literal["log(get_field(magnitudes, 'len'), 2)"]]],
|
380
|
+
) -> None:
|
381
|
+
"""
|
382
|
+
|
383
|
+
[Qmod Classiq-library function]
|
384
|
+
|
385
|
+
Initializes and prepares a quantum state with amplitudes and phases for each state according to the given parameters, in polar representation.
|
386
|
+
|
387
|
+
Args:
|
388
|
+
magnitudes: Absolute values of the state amplitudes.
|
389
|
+
phases: phases of the state amplitudes. should be of the same size as `amplitudes`.
|
390
|
+
out: The allocated quantum variable. Must be uninitialized.
|
391
|
+
"""
|
392
|
+
allocate(out)
|
393
|
+
inplace_prepare_complex_amplitudes(magnitudes, phases, out)
|
@@ -24,13 +24,16 @@ class ModelStateContainer:
|
|
24
24
|
generative_functions: dict[str, "GenerativeQFunc"]
|
25
25
|
function_dependencies: dict[str, list[str]]
|
26
26
|
|
27
|
+
def reset(self) -> None:
|
28
|
+
self.enum_decls = {}
|
29
|
+
self.type_decls = {}
|
30
|
+
self.qstruct_decls = {}
|
31
|
+
self.native_defs = {}
|
32
|
+
self.constants = {}
|
33
|
+
self.functions_compilation_metadata = {}
|
34
|
+
self.generative_functions = {}
|
35
|
+
self.function_dependencies = defaultdict(list)
|
36
|
+
|
27
37
|
|
28
38
|
QMODULE = ModelStateContainer()
|
29
|
-
QMODULE.
|
30
|
-
QMODULE.type_decls = {}
|
31
|
-
QMODULE.qstruct_decls = {}
|
32
|
-
QMODULE.native_defs = {}
|
33
|
-
QMODULE.constants = {}
|
34
|
-
QMODULE.functions_compilation_metadata = {}
|
35
|
-
QMODULE.generative_functions = {}
|
36
|
-
QMODULE.function_dependencies = defaultdict(list)
|
39
|
+
QMODULE.reset()
|
classiq/qmod/qmod_variable.py
CHANGED
@@ -22,7 +22,12 @@ from typing import ( # type: ignore[attr-defined]
|
|
22
22
|
|
23
23
|
from typing_extensions import ParamSpec, Self, _AnnotatedAlias
|
24
24
|
|
25
|
-
from classiq.interface.exceptions import
|
25
|
+
from classiq.interface.exceptions import (
|
26
|
+
ClassiqInternalError,
|
27
|
+
ClassiqNotImplementedError,
|
28
|
+
ClassiqValueError,
|
29
|
+
)
|
30
|
+
from classiq.interface.generator.arith.register_user_input import RegisterArithmeticInfo
|
26
31
|
from classiq.interface.generator.expressions.expression import Expression
|
27
32
|
from classiq.interface.generator.expressions.non_symbolic_expr import NonSymbolicExpr
|
28
33
|
from classiq.interface.generator.expressions.proxies.quantum.qmod_qarray_proxy import (
|
@@ -340,6 +345,23 @@ class QNum(Generic[_P], QScalar):
|
|
340
345
|
return interpret_expression(str(self.is_signed))
|
341
346
|
return CParamScalar(f"get_field({self}, 'is_signed')")
|
342
347
|
|
348
|
+
def get_maximal_bounds(self) -> tuple[float, float]:
|
349
|
+
if not is_generative_mode():
|
350
|
+
raise ClassiqNotImplementedError(
|
351
|
+
"get_maximal_bounds() is supported in generative mode only"
|
352
|
+
)
|
353
|
+
|
354
|
+
if TYPE_CHECKING:
|
355
|
+
assert isinstance(self.size, int)
|
356
|
+
assert isinstance(self.is_signed, bool)
|
357
|
+
assert isinstance(self.fraction_digits, int)
|
358
|
+
|
359
|
+
return RegisterArithmeticInfo.get_maximal_bounds(
|
360
|
+
size=self.size,
|
361
|
+
is_signed=self.is_signed,
|
362
|
+
fraction_places=self.fraction_digits,
|
363
|
+
)
|
364
|
+
|
343
365
|
# Support comma-separated generic args in older Python versions
|
344
366
|
if sys.version_info[0:2] < (3, 10):
|
345
367
|
|
classiq/qmod/quantum_function.py
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
import ast
|
2
2
|
import functools
|
3
3
|
from abc import abstractmethod
|
4
|
-
from collections import defaultdict
|
5
4
|
from dataclasses import is_dataclass
|
6
5
|
from enum import EnumMeta
|
7
6
|
from inspect import isclass
|
@@ -120,14 +119,7 @@ class QFunc(BaseQFunc):
|
|
120
119
|
preferences: Optional[Preferences] = None,
|
121
120
|
classical_execution_function: Optional[CFunc] = None,
|
122
121
|
) -> Model:
|
123
|
-
self._qmodule.
|
124
|
-
self._qmodule.type_decls = dict()
|
125
|
-
self._qmodule.qstruct_decls = dict()
|
126
|
-
self._qmodule.native_defs = dict()
|
127
|
-
self._qmodule.constants = dict()
|
128
|
-
self._qmodule.functions_compilation_metadata = dict()
|
129
|
-
self._qmodule.generative_functions = dict()
|
130
|
-
self._qmodule.function_dependencies = defaultdict(list)
|
122
|
+
self._qmodule.reset()
|
131
123
|
QConstant.set_current_model(self._qmodule)
|
132
124
|
self.expand()
|
133
125
|
model_extra_settings: list[tuple[str, Any]] = [
|
classiq/qmod/symbolic_expr.py
CHANGED
@@ -4,6 +4,8 @@ import ast
|
|
4
4
|
from enum import Enum as PythonEnum
|
5
5
|
from typing import Any
|
6
6
|
|
7
|
+
import sympy
|
8
|
+
|
7
9
|
from classiq.qmod.utilities import qmod_val_to_expr_str
|
8
10
|
|
9
11
|
|
@@ -33,10 +35,14 @@ class SymbolicExpr(Symbolic):
|
|
33
35
|
|
34
36
|
@staticmethod
|
35
37
|
def _binary_op(lhs: Any, rhs: Any, op: str) -> SymbolicExpr:
|
36
|
-
if not isinstance(
|
38
|
+
if not isinstance(
|
39
|
+
lhs, (SymbolicExpr, int, float, bool, PythonEnum, sympy.Basic)
|
40
|
+
):
|
37
41
|
raise TypeError(f"Invalid lhs argument {lhs!r} for binary operation {op!r}")
|
38
42
|
|
39
|
-
if not isinstance(
|
43
|
+
if not isinstance(
|
44
|
+
rhs, (SymbolicExpr, int, float, bool, PythonEnum, sympy.Basic)
|
45
|
+
):
|
40
46
|
raise TypeError(f"Invalid lhs argument {rhs!r} for binary operation {op!r}")
|
41
47
|
|
42
48
|
lhs_str = qmod_val_to_expr_str(lhs)
|
classiq/qmod/write_qmod.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import json
|
2
2
|
from pathlib import Path
|
3
|
-
from typing import Optional, Union
|
3
|
+
from typing import Any, Optional, Union
|
4
4
|
|
5
5
|
from classiq.interface.model.model import Model, SerializedModel
|
6
6
|
|
@@ -17,6 +17,8 @@ def write_qmod(
|
|
17
17
|
name: str,
|
18
18
|
directory: Optional[Path] = None,
|
19
19
|
decimal_precision: int = DEFAULT_DECIMAL_PRECISION,
|
20
|
+
*args: Any,
|
21
|
+
**kwargs: Any,
|
20
22
|
) -> None:
|
21
23
|
"""
|
22
24
|
Creates a native Qmod file from a serialized model and outputs the synthesis options (Preferences and Constraints) to a file.
|
@@ -27,6 +29,8 @@ def write_qmod(
|
|
27
29
|
name: The name to save the file by.
|
28
30
|
directory: The directory to save the files in. If None, the current working directory is used.
|
29
31
|
decimal_precision: The number of decimal places to use for numbers, set to 4 by default.
|
32
|
+
args: (placeholder)
|
33
|
+
kwargs: (placeholder)
|
30
34
|
|
31
35
|
Returns:
|
32
36
|
None
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: classiq
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.75.0
|
4
4
|
Summary: Classiq's Python SDK for quantum computing
|
5
5
|
License: Proprietary
|
6
6
|
Keywords: quantum computing,quantum circuits,quantum algorithms,QAD,QDL
|
@@ -53,6 +53,7 @@ Requires-Dist: tabulate (>=0.8.9,<1)
|
|
53
53
|
Requires-Dist: torch ; extra == "qml"
|
54
54
|
Requires-Dist: torchvision ; extra == "qml"
|
55
55
|
Requires-Dist: tqdm (>=4.67.1,<5.0.0)
|
56
|
+
Requires-Dist: zstandard (>=0.23.0,<0.24.0)
|
56
57
|
Description-Content-Type: text/markdown
|
57
58
|
|
58
59
|
<p align="center">
|