classiq 0.75.0__py3-none-any.whl → 0.76.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 +36 -0
- classiq/analyzer/show_interactive_hack.py +58 -2
- classiq/applications/chemistry/chemistry_model_constructor.py +8 -1
- classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +2 -0
- classiq/applications/combinatorial_optimization/combinatorial_problem.py +4 -4
- classiq/applications/qnn/gradients/quantum_gradient.py +3 -5
- classiq/applications/qnn/gradients/simple_quantum_gradient.py +2 -2
- classiq/applications/qnn/qlayer.py +14 -19
- classiq/applications/qnn/types.py +1 -4
- classiq/execution/__init__.py +3 -0
- classiq/execution/execution_session.py +3 -16
- classiq/execution/qnn.py +2 -2
- classiq/execution/user_budgets.py +38 -0
- classiq/executor.py +7 -19
- classiq/interface/_version.py +1 -1
- classiq/interface/debug_info/debug_info.py +16 -2
- classiq/interface/executor/user_budget.py +56 -0
- classiq/interface/generator/application_apis/finance_declarations.py +3 -0
- classiq/interface/generator/expressions/atomic_expression_functions.py +3 -0
- classiq/interface/generator/expressions/proxies/classical/any_classical_value.py +30 -124
- classiq/interface/generator/expressions/proxies/classical/classical_array_proxy.py +45 -21
- classiq/interface/generator/expressions/proxies/classical/qmod_struct_instance.py +7 -0
- classiq/interface/generator/expressions/proxies/classical/utils.py +12 -11
- classiq/interface/generator/expressions/proxies/quantum/qmod_qscalar_proxy.py +9 -2
- classiq/interface/generator/expressions/proxies/quantum/qmod_sized_proxy.py +4 -1
- classiq/interface/generator/expressions/sympy_supported_expressions.py +1 -0
- classiq/interface/generator/functions/classical_type.py +6 -1
- classiq/interface/generator/functions/type_name.py +7 -2
- classiq/interface/generator/functions/type_qualifier.py +15 -0
- classiq/interface/generator/model/preferences/preferences.py +7 -0
- classiq/interface/generator/quantum_program.py +5 -19
- classiq/interface/helpers/backward_compatibility.py +9 -0
- classiq/interface/helpers/datastructures.py +6 -0
- classiq/interface/model/port_declaration.py +1 -2
- classiq/interface/model/quantum_lambda_function.py +2 -1
- classiq/interface/server/routes.py +6 -0
- classiq/model_expansions/atomic_expression_functions_defs.py +62 -19
- classiq/model_expansions/capturing/captured_vars.py +2 -0
- classiq/model_expansions/closure.py +5 -0
- classiq/model_expansions/evaluators/classical_type_inference.py +17 -6
- classiq/model_expansions/evaluators/parameter_types.py +26 -13
- classiq/model_expansions/expression_evaluator.py +1 -1
- classiq/model_expansions/generative_functions.py +61 -34
- classiq/model_expansions/interpreters/base_interpreter.py +17 -6
- classiq/model_expansions/interpreters/frontend_generative_interpreter.py +5 -0
- classiq/model_expansions/interpreters/generative_interpreter.py +13 -1
- classiq/model_expansions/quantum_operations/allocate.py +6 -1
- classiq/model_expansions/quantum_operations/assignment_result_processor.py +219 -20
- classiq/model_expansions/quantum_operations/bind.py +54 -30
- classiq/model_expansions/quantum_operations/block_evaluator.py +42 -0
- classiq/model_expansions/quantum_operations/call_emitter.py +14 -7
- classiq/model_expansions/quantum_operations/composite_emitter.py +1 -1
- classiq/model_expansions/quantum_operations/declarative_call_emitter.py +23 -9
- classiq/model_expansions/quantum_operations/emitter.py +20 -3
- classiq/model_expansions/quantum_operations/quantum_function_call.py +4 -3
- classiq/model_expansions/scope.py +10 -7
- classiq/model_expansions/sympy_conversion/arithmetics.py +18 -0
- classiq/model_expansions/sympy_conversion/expression_to_sympy.py +2 -0
- classiq/model_expansions/sympy_conversion/sympy_to_python.py +10 -1
- classiq/model_expansions/transformers/model_renamer.py +45 -7
- classiq/model_expansions/utils/handles_collector.py +1 -1
- classiq/model_expansions/visitors/variable_references.py +45 -9
- classiq/qmod/builtins/functions/allocation.py +2 -2
- classiq/qmod/builtins/functions/arithmetic.py +14 -12
- classiq/qmod/builtins/functions/standard_gates.py +23 -23
- classiq/qmod/declaration_inferrer.py +19 -7
- classiq/qmod/generative.py +9 -1
- classiq/qmod/native/expression_to_qmod.py +4 -0
- classiq/qmod/native/pretty_printer.py +8 -3
- classiq/qmod/pretty_print/pretty_printer.py +1 -1
- classiq/qmod/python_classical_type.py +4 -5
- classiq/qmod/qmod_constant.py +15 -7
- classiq/qmod/qmod_variable.py +7 -1
- classiq/qmod/quantum_function.py +19 -6
- classiq/qmod/semantics/lambdas.py +6 -2
- classiq/qmod/semantics/validation/main_validation.py +17 -4
- classiq/qmod/symbolic.py +8 -19
- classiq/qmod/symbolic_expr.py +26 -0
- classiq/synthesis.py +17 -31
- classiq/visualization.py +35 -0
- {classiq-0.75.0.dist-info → classiq-0.76.0.dist-info}/METADATA +1 -1
- {classiq-0.75.0.dist-info → classiq-0.76.0.dist-info}/RECORD +83 -79
- {classiq-0.75.0.dist-info → classiq-0.76.0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,56 @@
|
|
1
|
+
import datetime
|
2
|
+
from collections import defaultdict
|
3
|
+
from typing import Optional
|
4
|
+
|
5
|
+
import pydantic
|
6
|
+
from pydantic import ConfigDict, Field
|
7
|
+
|
8
|
+
from classiq.interface.helpers.versioned_model import VersionedModel
|
9
|
+
|
10
|
+
|
11
|
+
class UserBudget(VersionedModel):
|
12
|
+
provider: str
|
13
|
+
currency_code: str
|
14
|
+
organization: Optional[str] = Field(default=None)
|
15
|
+
available_budget: float
|
16
|
+
used_budget: float
|
17
|
+
last_allocation_date: datetime.datetime
|
18
|
+
|
19
|
+
model_config = ConfigDict(extra="ignore")
|
20
|
+
|
21
|
+
|
22
|
+
class UserBudgets(VersionedModel):
|
23
|
+
budgets: list[UserBudget] = pydantic.Field(default=[])
|
24
|
+
|
25
|
+
def print_budgets(self) -> None:
|
26
|
+
def format_header() -> str:
|
27
|
+
return f"| {'Provider':<20} | {'Available Budget':<18} | {'Used Budget':<18} | {'Currency':<8} |"
|
28
|
+
|
29
|
+
def format_row(
|
30
|
+
provider: str, available: float, used: float, currency: str
|
31
|
+
) -> str:
|
32
|
+
return f"| {provider:<20} | {available:<18.0f} | {used:<18.0f} | {currency:<8} |"
|
33
|
+
|
34
|
+
table_data: dict = defaultdict(
|
35
|
+
lambda: {"used": 0.0, "available": 0.0, "currency": "USD"}
|
36
|
+
)
|
37
|
+
|
38
|
+
for budget in self.budgets:
|
39
|
+
provider = budget.provider
|
40
|
+
table_data[provider]["available"] += budget.available_budget
|
41
|
+
table_data[provider]["used"] += budget.used_budget
|
42
|
+
table_data[provider]["currency"] = budget.currency_code
|
43
|
+
|
44
|
+
line = "=" * 77
|
45
|
+
print(line) # noqa: T201
|
46
|
+
print(format_header()) # noqa: T201
|
47
|
+
print(line) # noqa: T201
|
48
|
+
|
49
|
+
for provider, values in table_data.items():
|
50
|
+
print( # noqa: T201
|
51
|
+
format_row(
|
52
|
+
provider, values["available"], values["used"], values["currency"]
|
53
|
+
)
|
54
|
+
)
|
55
|
+
|
56
|
+
print(line) # noqa: T201
|
@@ -10,6 +10,7 @@ from classiq.interface.generator.functions.port_declaration import (
|
|
10
10
|
PortDeclarationDirection,
|
11
11
|
)
|
12
12
|
from classiq.interface.generator.functions.type_name import Struct
|
13
|
+
from classiq.interface.generator.functions.type_qualifier import TypeQualifier
|
13
14
|
from classiq.interface.model.classical_parameter_declaration import (
|
14
15
|
ClassicalParameterDeclaration,
|
15
16
|
)
|
@@ -55,11 +56,13 @@ def _generate_finance_function(
|
|
55
56
|
)
|
56
57
|
),
|
57
58
|
direction=PortDeclarationDirection.Inout,
|
59
|
+
type_qualifier=TypeQualifier.Quantum,
|
58
60
|
),
|
59
61
|
PortDeclaration(
|
60
62
|
name=OBJECTIVE_PORT_NAME,
|
61
63
|
quantum_type=QuantumBit(),
|
62
64
|
direction=PortDeclarationDirection.Inout,
|
65
|
+
type_qualifier=TypeQualifier.Quantum,
|
63
66
|
),
|
64
67
|
],
|
65
68
|
)
|
@@ -15,6 +15,7 @@ SUPPORTED_CLASSIQ_BUILTIN_FUNCTIONS = {
|
|
15
15
|
"molecule_problem_to_hamiltonian",
|
16
16
|
"fock_hamiltonian_problem_to_hamiltonian",
|
17
17
|
"molecule_ground_state_solution_post_process",
|
18
|
+
"mod_inverse",
|
18
19
|
}
|
19
20
|
|
20
21
|
SUPPORTED_CLASSIQ_SYMPY_WRAPPERS = {
|
@@ -23,6 +24,8 @@ SUPPORTED_CLASSIQ_SYMPY_WRAPPERS = {
|
|
23
24
|
"BitwiseNot",
|
24
25
|
"BitwiseOr",
|
25
26
|
"LogicalXor",
|
27
|
+
"RShift",
|
28
|
+
"LShift",
|
26
29
|
}
|
27
30
|
|
28
31
|
SUPPORTED_ATOMIC_EXPRESSION_FUNCTIONS = {
|
@@ -1,135 +1,41 @@
|
|
1
|
+
import inspect
|
1
2
|
from typing import Any
|
2
3
|
|
4
|
+
import sympy
|
3
5
|
|
4
|
-
|
5
|
-
def __init__(self, expr: str) -> None:
|
6
|
-
self._expr = expr
|
6
|
+
_SYMPY_MEMBERS = [name for name, _ in inspect.getmembers(sympy.Symbol)] + ["precedence"]
|
7
7
|
|
8
|
-
def __str__(self) -> str:
|
9
|
-
return self._expr
|
10
8
|
|
11
|
-
|
12
|
-
|
9
|
+
def subscript_to_str(index: Any) -> str:
|
10
|
+
if not isinstance(index, slice):
|
11
|
+
return str(index)
|
12
|
+
expr = ""
|
13
|
+
if index.start is not None:
|
14
|
+
expr += str(index.start)
|
15
|
+
expr += ":"
|
16
|
+
if index.stop is not None:
|
17
|
+
expr += str(index.stop)
|
18
|
+
if index.step is not None:
|
19
|
+
expr += f":{index.step}"
|
20
|
+
return expr
|
13
21
|
|
14
|
-
def __getitem__(self, item: Any) -> "AnyClassicalValue":
|
15
|
-
if isinstance(item, slice):
|
16
|
-
subscript = ""
|
17
|
-
if item.start is not None:
|
18
|
-
subscript += str(item.start)
|
19
|
-
subscript += ":"
|
20
|
-
if item.stop is not None:
|
21
|
-
subscript += str(item.stop)
|
22
|
-
if item.step is not None:
|
23
|
-
subscript += f":{item.stop}"
|
24
|
-
item = subscript
|
25
|
-
return AnyClassicalValue(f"{self}[{item}]")
|
26
|
-
|
27
|
-
@staticmethod
|
28
|
-
def _binary_op(lhs: Any, rhs: Any, op: str) -> "AnyClassicalValue":
|
29
|
-
return AnyClassicalValue(f"{lhs} {op} {rhs}")
|
30
|
-
|
31
|
-
@staticmethod
|
32
|
-
def _unary_op(arg: Any, op: str) -> "AnyClassicalValue":
|
33
|
-
return AnyClassicalValue(f"{op}({arg})")
|
34
|
-
|
35
|
-
def __add__(self, other: Any) -> "AnyClassicalValue":
|
36
|
-
return AnyClassicalValue._binary_op(self, other, "+")
|
37
|
-
|
38
|
-
def __sub__(self, other: Any) -> "AnyClassicalValue":
|
39
|
-
return AnyClassicalValue._binary_op(self, other, "-")
|
40
|
-
|
41
|
-
def __mul__(self, other: Any) -> "AnyClassicalValue":
|
42
|
-
return AnyClassicalValue._binary_op(self, other, "*")
|
43
|
-
|
44
|
-
def __truediv__(self, other: Any) -> "AnyClassicalValue":
|
45
|
-
return AnyClassicalValue._binary_op(self, other, "/")
|
46
|
-
|
47
|
-
def __floordiv__(self, other: Any) -> "AnyClassicalValue":
|
48
|
-
return AnyClassicalValue._binary_op(self, other, "//")
|
49
|
-
|
50
|
-
def __mod__(self, other: Any) -> "AnyClassicalValue":
|
51
|
-
return AnyClassicalValue._binary_op(self, other, "%")
|
52
|
-
|
53
|
-
def __pow__(self, other: Any) -> "AnyClassicalValue":
|
54
|
-
return AnyClassicalValue._binary_op(self, other, "**")
|
55
|
-
|
56
|
-
def __lshift__(self, other: Any) -> "AnyClassicalValue":
|
57
|
-
return AnyClassicalValue._binary_op(self, other, "<<")
|
58
|
-
|
59
|
-
def __rshift__(self, other: Any) -> "AnyClassicalValue":
|
60
|
-
return AnyClassicalValue._binary_op(self, other, ">>")
|
61
|
-
|
62
|
-
def __and__(self, other: Any) -> "AnyClassicalValue":
|
63
|
-
return AnyClassicalValue._binary_op(self, other, "&")
|
64
|
-
|
65
|
-
def __xor__(self, other: Any) -> "AnyClassicalValue":
|
66
|
-
return AnyClassicalValue._binary_op(self, other, "^")
|
67
|
-
|
68
|
-
def __or__(self, other: Any) -> "AnyClassicalValue":
|
69
|
-
return AnyClassicalValue._binary_op(self, other, "|")
|
70
|
-
|
71
|
-
def __radd__(self, other: Any) -> "AnyClassicalValue":
|
72
|
-
return AnyClassicalValue._binary_op(other, self, "+")
|
73
|
-
|
74
|
-
def __rsub__(self, other: Any) -> "AnyClassicalValue":
|
75
|
-
return AnyClassicalValue._binary_op(other, self, "-")
|
76
22
|
|
77
|
-
|
78
|
-
return AnyClassicalValue._binary_op(other, self, "*")
|
23
|
+
class AnyClassicalValue(sympy.Symbol):
|
79
24
|
|
80
|
-
|
81
|
-
|
25
|
+
is_commutative = None
|
26
|
+
is_infinite = None
|
27
|
+
is_finite = None
|
28
|
+
is_extended_real = None
|
82
29
|
|
83
|
-
def
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
return AnyClassicalValue._binary_op(other, self, "%")
|
88
|
-
|
89
|
-
def __rpow__(self, other: Any) -> "AnyClassicalValue":
|
90
|
-
return AnyClassicalValue._binary_op(other, self, "**")
|
91
|
-
|
92
|
-
def __rlshift__(self, other: Any) -> "AnyClassicalValue":
|
93
|
-
return AnyClassicalValue._binary_op(other, self, "<<")
|
94
|
-
|
95
|
-
def __rrshift__(self, other: Any) -> "AnyClassicalValue":
|
96
|
-
return AnyClassicalValue._binary_op(other, self, ">>")
|
97
|
-
|
98
|
-
def __rand__(self, other: Any) -> "AnyClassicalValue":
|
99
|
-
return AnyClassicalValue._binary_op(other, self, "&")
|
100
|
-
|
101
|
-
def __rxor__(self, other: Any) -> "AnyClassicalValue":
|
102
|
-
return AnyClassicalValue._binary_op(other, self, "^")
|
103
|
-
|
104
|
-
def __ror__(self, other: Any) -> "AnyClassicalValue":
|
105
|
-
return AnyClassicalValue._binary_op(other, self, "|")
|
106
|
-
|
107
|
-
def __lt__(self, other: Any) -> "AnyClassicalValue":
|
108
|
-
return AnyClassicalValue._binary_op(self, other, "<")
|
109
|
-
|
110
|
-
def __le__(self, other: Any) -> "AnyClassicalValue":
|
111
|
-
return AnyClassicalValue._binary_op(self, other, "<=")
|
112
|
-
|
113
|
-
def __eq__(self, other: Any) -> "AnyClassicalValue": # type:ignore[override]
|
114
|
-
return AnyClassicalValue._binary_op(self, other, "==")
|
115
|
-
|
116
|
-
def __ne__(self, other: Any) -> "AnyClassicalValue": # type: ignore[override]
|
117
|
-
return AnyClassicalValue._binary_op(self, other, "!=")
|
118
|
-
|
119
|
-
def __gt__(self, other: Any) -> "AnyClassicalValue":
|
120
|
-
return AnyClassicalValue._binary_op(self, other, ">")
|
121
|
-
|
122
|
-
def __ge__(self, other: Any) -> "AnyClassicalValue":
|
123
|
-
return AnyClassicalValue._binary_op(self, other, ">=")
|
124
|
-
|
125
|
-
def __neg__(self) -> "AnyClassicalValue":
|
126
|
-
return AnyClassicalValue._unary_op(self, "-")
|
127
|
-
|
128
|
-
def __pos__(self) -> "AnyClassicalValue":
|
129
|
-
return AnyClassicalValue._unary_op(self, "+")
|
30
|
+
def __getitem__(self, item: Any) -> "AnyClassicalValue":
|
31
|
+
if isinstance(item, slice):
|
32
|
+
return AnyClassicalValue(f"{self}[{subscript_to_str(item)}]")
|
33
|
+
return AnyClassicalValue(f"do_subscript({self}, {item})")
|
130
34
|
|
131
|
-
def
|
132
|
-
|
35
|
+
def __getattribute__(self, attr: str) -> Any:
|
36
|
+
if attr.startswith("_") or attr in _SYMPY_MEMBERS:
|
37
|
+
return super().__getattribute__(attr)
|
38
|
+
return AnyClassicalValue(f"get_field({self}, '{attr}')")
|
133
39
|
|
134
|
-
def
|
135
|
-
return
|
40
|
+
def __len__(self) -> "AnyClassicalValue":
|
41
|
+
return self.len
|
@@ -1,11 +1,16 @@
|
|
1
1
|
from collections.abc import Mapping
|
2
|
-
from typing import TYPE_CHECKING, Union
|
2
|
+
from typing import TYPE_CHECKING, Any, Union
|
3
3
|
|
4
|
+
import sympy
|
4
5
|
from sympy import Integer
|
6
|
+
from typing_extensions import TypeGuard
|
5
7
|
|
6
8
|
from classiq.interface.exceptions import ClassiqIndexError
|
7
9
|
from classiq.interface.generator.expressions.expression import Expression
|
8
10
|
from classiq.interface.generator.expressions.non_symbolic_expr import NonSymbolicExpr
|
11
|
+
from classiq.interface.generator.expressions.proxies.classical.any_classical_value import (
|
12
|
+
AnyClassicalValue,
|
13
|
+
)
|
9
14
|
from classiq.interface.generator.expressions.proxies.classical.classical_proxy import (
|
10
15
|
ClassicalProxy,
|
11
16
|
)
|
@@ -22,9 +27,20 @@ if TYPE_CHECKING:
|
|
22
27
|
)
|
23
28
|
|
24
29
|
|
30
|
+
def _is_int(val: Any) -> TypeGuard[Union[int, sympy.Basic]]:
|
31
|
+
if isinstance(val, AnyClassicalValue):
|
32
|
+
return False
|
33
|
+
if isinstance(val, sympy.Basic):
|
34
|
+
return val.is_Number
|
35
|
+
return isinstance(val, int)
|
36
|
+
|
37
|
+
|
25
38
|
class ClassicalArrayProxy(NonSymbolicExpr, ClassicalProxy):
|
26
39
|
def __init__(
|
27
|
-
self,
|
40
|
+
self,
|
41
|
+
handle: HandleBinding,
|
42
|
+
element_type: "ConcreteClassicalType",
|
43
|
+
length: "ExpressionValue",
|
28
44
|
) -> None:
|
29
45
|
super().__init__(handle)
|
30
46
|
self._element_type = element_type
|
@@ -39,39 +55,47 @@ class ClassicalArrayProxy(NonSymbolicExpr, ClassicalProxy):
|
|
39
55
|
return "Array"
|
40
56
|
|
41
57
|
@property
|
42
|
-
def length(self) ->
|
58
|
+
def length(self) -> "ExpressionValue":
|
43
59
|
return self._length
|
44
60
|
|
45
|
-
def __getitem__(
|
61
|
+
def __getitem__(
|
62
|
+
self, key: Union[slice, int, Integer, ClassicalProxy]
|
63
|
+
) -> ClassicalProxy:
|
46
64
|
return (
|
47
65
|
self._get_slice(key) if isinstance(key, slice) else self._get_subscript(key)
|
48
66
|
)
|
49
67
|
|
50
68
|
def _get_slice(self, slice_: slice) -> ClassicalProxy:
|
51
|
-
|
52
|
-
|
53
|
-
if
|
54
|
-
|
55
|
-
|
56
|
-
|
69
|
+
start_ = slice_.start
|
70
|
+
stop_ = slice_.stop
|
71
|
+
if _is_int(start_) and _is_int(stop_):
|
72
|
+
start = int(start_)
|
73
|
+
stop = int(stop_)
|
74
|
+
if start >= stop:
|
75
|
+
raise ClassiqIndexError("Array slice has non-positive length")
|
76
|
+
if start < 0 or (isinstance(self._length, int) and stop > self._length):
|
77
|
+
raise ClassiqIndexError("Array slice is out of bounds")
|
57
78
|
return ClassicalArrayProxy(
|
58
79
|
SlicedHandleBinding(
|
59
80
|
base_handle=self.handle,
|
60
|
-
start=Expression(expr=str(
|
61
|
-
end=Expression(expr=str(
|
81
|
+
start=Expression(expr=str(start_)),
|
82
|
+
end=Expression(expr=str(stop_)),
|
62
83
|
),
|
63
84
|
self._element_type,
|
64
|
-
|
85
|
+
stop_ - start_,
|
65
86
|
)
|
66
87
|
|
67
|
-
def _get_subscript(
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
88
|
+
def _get_subscript(
|
89
|
+
self, index_: Union[int, Integer, ClassicalProxy]
|
90
|
+
) -> ClassicalProxy:
|
91
|
+
if _is_int(index_):
|
92
|
+
index = int(index_)
|
93
|
+
if index < 0:
|
94
|
+
raise ClassiqIndexError(
|
95
|
+
"Array index is out of bounds (negative indices are not supported)"
|
96
|
+
)
|
97
|
+
if isinstance(self._length, int) and index >= self._length:
|
98
|
+
raise ClassiqIndexError("Array index is out of bounds")
|
75
99
|
return self._element_type.get_classical_proxy(
|
76
100
|
SubscriptHandleBinding(
|
77
101
|
base_handle=self._handle, index=Expression(expr=str(index_))
|
@@ -25,6 +25,13 @@ class QmodStructInstance:
|
|
25
25
|
def fields(self) -> Mapping[str, Any]:
|
26
26
|
return types.MappingProxyType(self._fields)
|
27
27
|
|
28
|
+
def __getattr__(self, item: str) -> Any:
|
29
|
+
if item == "_fields":
|
30
|
+
return super().__getattribute__(item)
|
31
|
+
if item in self._fields:
|
32
|
+
return self._fields[item]
|
33
|
+
return super().__getattribute__(item)
|
34
|
+
|
28
35
|
def __str__(self) -> str:
|
29
36
|
return repr(self)
|
30
37
|
|
@@ -13,6 +13,7 @@ from classiq.interface.generator.expressions.proxies.classical.classical_struct_
|
|
13
13
|
)
|
14
14
|
from classiq.interface.generator.functions.classical_type import (
|
15
15
|
ClassicalArray,
|
16
|
+
ClassicalList,
|
16
17
|
ClassicalType,
|
17
18
|
)
|
18
19
|
from classiq.interface.generator.functions.type_name import Struct
|
@@ -20,15 +21,15 @@ from classiq.interface.generator.functions.type_name import Struct
|
|
20
21
|
|
21
22
|
def get_proxy_type(proxy: ClassicalProxy) -> ClassicalType:
|
22
23
|
if isinstance(proxy, ClassicalScalarProxy):
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
element_type=proxy._element_type
|
27
|
-
)
|
28
|
-
|
24
|
+
return proxy._classical_type
|
25
|
+
if isinstance(proxy, ClassicalArrayProxy):
|
26
|
+
if not isinstance(proxy.length, int):
|
27
|
+
return ClassicalList(element_type=proxy._element_type)
|
28
|
+
return ClassicalArray(element_type=proxy._element_type, size=proxy.length)
|
29
|
+
if isinstance(proxy, ClassicalStructProxy):
|
29
30
|
classical_type = Struct(name=proxy._decl.name)
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
)
|
34
|
-
|
31
|
+
classical_type.set_classical_struct_decl(proxy._decl)
|
32
|
+
return classical_type
|
33
|
+
raise ClassiqInternalExpansionError(
|
34
|
+
f"Unrecognized classical proxy {type(proxy).__name__}"
|
35
|
+
)
|
@@ -1,7 +1,8 @@
|
|
1
1
|
from collections.abc import Mapping
|
2
|
-
from typing import Any
|
2
|
+
from typing import Any, Optional
|
3
3
|
|
4
4
|
from sympy import Symbol
|
5
|
+
from typing_extensions import Self
|
5
6
|
|
6
7
|
from classiq.interface.exceptions import ClassiqValueError
|
7
8
|
from classiq.interface.generator.expressions.proxies.quantum.qmod_sized_proxy import (
|
@@ -12,11 +13,17 @@ from classiq.interface.model.handle_binding import HandleBinding
|
|
12
13
|
|
13
14
|
class QmodQScalarProxy(Symbol, QmodSizedProxy):
|
14
15
|
def __new__(cls, handle: HandleBinding, **assumptions: bool) -> "QmodQScalarProxy":
|
15
|
-
return super().__new__(cls,
|
16
|
+
return super().__new__(cls, handle.qmod_expr, **assumptions)
|
16
17
|
|
17
18
|
def __init__(self, handle: HandleBinding, size: int) -> None:
|
18
19
|
super().__init__(handle, size)
|
19
20
|
|
21
|
+
def __copy__(self) -> Self:
|
22
|
+
return self
|
23
|
+
|
24
|
+
def __deepcopy__(self, memo: Optional[dict]) -> Self:
|
25
|
+
return self
|
26
|
+
|
20
27
|
|
21
28
|
class QmodQBitProxy(QmodQScalarProxy):
|
22
29
|
def __init__(self, handle: HandleBinding) -> None:
|
@@ -6,6 +6,9 @@ from typing_extensions import Self
|
|
6
6
|
|
7
7
|
from classiq.interface.ast_node import HashableASTNode
|
8
8
|
from classiq.interface.generator.expressions.expression import Expression
|
9
|
+
from classiq.interface.generator.expressions.proxies.classical.any_classical_value import (
|
10
|
+
AnyClassicalValue,
|
11
|
+
)
|
9
12
|
from classiq.interface.generator.expressions.proxies.classical.classical_array_proxy import (
|
10
13
|
ClassicalArrayProxy,
|
11
14
|
)
|
@@ -94,7 +97,9 @@ class ClassicalList(ClassicalType):
|
|
94
97
|
return values_with_discriminator(values, "kind", "list")
|
95
98
|
|
96
99
|
def get_classical_proxy(self, handle: HandleBinding) -> ClassicalProxy:
|
97
|
-
|
100
|
+
return ClassicalArrayProxy(
|
101
|
+
handle, self.element_type, AnyClassicalValue(f"get_field({handle}, 'len')")
|
102
|
+
)
|
98
103
|
|
99
104
|
@property
|
100
105
|
def expressions(self) -> list[Expression]:
|
@@ -9,6 +9,9 @@ from classiq.interface.generator.expressions.expression import Expression
|
|
9
9
|
from classiq.interface.generator.expressions.proxies.classical.classical_proxy import (
|
10
10
|
ClassicalProxy,
|
11
11
|
)
|
12
|
+
from classiq.interface.generator.expressions.proxies.classical.classical_scalar_proxy import (
|
13
|
+
ClassicalScalarProxy,
|
14
|
+
)
|
12
15
|
from classiq.interface.generator.expressions.proxies.classical.classical_struct_proxy import (
|
13
16
|
ClassicalStructProxy,
|
14
17
|
)
|
@@ -109,8 +112,10 @@ class TypeName(ClassicalType, QuantumType):
|
|
109
112
|
self._classical_struct_decl = decl
|
110
113
|
|
111
114
|
def get_classical_proxy(self, handle: HandleBinding) -> ClassicalProxy:
|
112
|
-
if self.
|
113
|
-
|
115
|
+
if self.is_enum:
|
116
|
+
return ClassicalScalarProxy(handle, self)
|
117
|
+
if TYPE_CHECKING:
|
118
|
+
assert self._classical_struct_decl is not None
|
114
119
|
return ClassicalStructProxy(handle, self._classical_struct_decl)
|
115
120
|
|
116
121
|
@property
|
@@ -1,7 +1,22 @@
|
|
1
1
|
from classiq.interface.enum_utils import StrEnum
|
2
|
+
from classiq.interface.exceptions import ClassiqInternalExpansionError
|
2
3
|
|
3
4
|
|
4
5
|
class TypeQualifier(StrEnum):
|
5
6
|
Const = "const"
|
6
7
|
QFree = "qfree"
|
7
8
|
Quantum = "quantum"
|
9
|
+
Inferred = "inferred"
|
10
|
+
|
11
|
+
@staticmethod
|
12
|
+
def and_(first: "TypeQualifier", second: "TypeQualifier") -> "TypeQualifier":
|
13
|
+
if second is TypeQualifier.Inferred:
|
14
|
+
raise ClassiqInternalExpansionError
|
15
|
+
if first is TypeQualifier.Quantum or second is TypeQualifier.Quantum:
|
16
|
+
return TypeQualifier.Quantum
|
17
|
+
elif first is TypeQualifier.QFree or second is TypeQualifier.QFree:
|
18
|
+
return TypeQualifier.QFree
|
19
|
+
else:
|
20
|
+
if first is not TypeQualifier.Const and second is not TypeQualifier.Const:
|
21
|
+
raise ClassiqInternalExpansionError("Unexpected type qualifiers")
|
22
|
+
return TypeQualifier.Const
|
@@ -102,6 +102,13 @@ class Preferences(pydantic.BaseModel, extra="forbid"):
|
|
102
102
|
debug_mode (bool): If `True`, debug information is added to the
|
103
103
|
synthesized result, potentially slowing down the synthesis. Useful for
|
104
104
|
executing interactive algorithms. Defaults to `True`.
|
105
|
+
optimization_level (OptimizationLevel) : The optimization level used during synthesis (0-3);
|
106
|
+
determines the trade-off between synthesis speed and the quality of the results. Defaults to 3.
|
107
|
+
OptimizationLevel Options:
|
108
|
+
- NONE = 0
|
109
|
+
- LIGHT = 1
|
110
|
+
- MEDIUM = 2
|
111
|
+
- HIGH = 3
|
105
112
|
output_format (List[QuantumFormat]): Lists the output format(s)
|
106
113
|
for the quantum circuit. Defaults to `[QuantumFormat.QASM]`.
|
107
114
|
`QuantumFormat` Options:
|
@@ -1,11 +1,9 @@
|
|
1
1
|
import uuid
|
2
2
|
from datetime import datetime, timezone
|
3
3
|
from pathlib import Path
|
4
|
-
from typing import
|
4
|
+
from typing import Optional, Union
|
5
5
|
|
6
6
|
import pydantic
|
7
|
-
from pydantic import model_validator
|
8
|
-
from pydantic_core.core_schema import ValidationInfo
|
9
7
|
from typing_extensions import TypeAlias
|
10
8
|
|
11
9
|
from classiq.interface.compression_utils import decompress
|
@@ -39,8 +37,6 @@ from classiq.interface.ide.visual_model import CircuitMetrics
|
|
39
37
|
RegisterName: TypeAlias = str
|
40
38
|
InitialConditions: TypeAlias = dict[RegisterName, int]
|
41
39
|
|
42
|
-
OMIT_DEBUG_INFO_FLAG = "omit_debug_info"
|
43
|
-
|
44
40
|
|
45
41
|
class TranspiledCircuitData(CircuitCodeInterface):
|
46
42
|
depth: int
|
@@ -77,18 +73,8 @@ class QuantumProgram(VersionedModel, CircuitCodeInterface):
|
|
77
73
|
program_id: str = pydantic.Field(default_factory=get_uuid_as_str)
|
78
74
|
execution_primitives_input: Optional[PrimitivesInput] = pydantic.Field(default=None)
|
79
75
|
|
80
|
-
|
81
|
-
|
82
|
-
def remove_debug_info(
|
83
|
-
cls, data: dict[str, Any], info: ValidationInfo
|
84
|
-
) -> dict[str, Any]:
|
85
|
-
if (
|
86
|
-
isinstance(data, dict)
|
87
|
-
and info.context is not None
|
88
|
-
and info.context.get(OMIT_DEBUG_INFO_FLAG, False)
|
89
|
-
):
|
90
|
-
data.pop("debug_info", None)
|
91
|
-
return data
|
76
|
+
def __str__(self) -> str:
|
77
|
+
return self.model_dump_json(indent=2)
|
92
78
|
|
93
79
|
def _hardware_agnostic_program_code(self) -> CodeAndSyntax:
|
94
80
|
circuit_code = self.program_circuit.get_code_by_priority()
|
@@ -177,7 +163,7 @@ class QuantumProgram(VersionedModel, CircuitCodeInterface):
|
|
177
163
|
file.write(self.model_dump_json(indent=4))
|
178
164
|
|
179
165
|
@classmethod
|
180
|
-
def from_qprog(cls, qprog:
|
166
|
+
def from_qprog(cls, qprog: "QuantumProgram") -> "QuantumProgram":
|
181
167
|
"""
|
182
168
|
Creates a `QuantumProgram` instance from a raw quantum program string.
|
183
169
|
|
@@ -187,7 +173,7 @@ class QuantumProgram(VersionedModel, CircuitCodeInterface):
|
|
187
173
|
Returns:
|
188
174
|
QuantumProgram: The `QuantumProgram` instance.
|
189
175
|
"""
|
190
|
-
return
|
176
|
+
return qprog
|
191
177
|
|
192
178
|
@property
|
193
179
|
def _can_use_transpiled_code(self) -> bool:
|
@@ -17,6 +17,12 @@ class LenList(list):
|
|
17
17
|
def len(self) -> int:
|
18
18
|
return len(self)
|
19
19
|
|
20
|
+
def __getitem__(self, item: Any) -> Any:
|
21
|
+
res = super().__getitem__(item)
|
22
|
+
if isinstance(item, slice):
|
23
|
+
res = type(self)(res)
|
24
|
+
return res
|
25
|
+
|
20
26
|
|
21
27
|
def get_sdk_compatible_python_object(obj: Any) -> Any:
|
22
28
|
if isinstance(obj, list):
|
@@ -16,8 +16,7 @@ from classiq.interface.model.parameter import Parameter
|
|
16
16
|
class AnonPortDeclaration(Parameter):
|
17
17
|
quantum_type: ConcreteQuantumType
|
18
18
|
direction: PortDeclarationDirection
|
19
|
-
|
20
|
-
type_qualifier: TypeQualifier = pydantic.Field(default=TypeQualifier.Quantum)
|
19
|
+
type_qualifier: TypeQualifier
|
21
20
|
kind: Literal["PortDeclaration"]
|
22
21
|
|
23
22
|
@pydantic.model_validator(mode="before")
|