classiq 0.100.0__py3-none-any.whl → 0.104.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 +3 -0
- classiq/_internals/api_wrapper.py +29 -4
- classiq/applications/chemistry/op_utils.py +63 -1
- classiq/applications/chemistry/problems.py +18 -6
- classiq/applications/chemistry/ucc.py +2 -2
- classiq/evaluators/parameter_types.py +1 -4
- classiq/evaluators/qmod_annotated_expression.py +1 -1
- classiq/evaluators/qmod_expression_visitors/qmod_expression_evaluator.py +1 -8
- classiq/evaluators/qmod_expression_visitors/qmod_expression_simplifier.py +1 -1
- classiq/evaluators/qmod_node_evaluators/attribute_evaluation.py +2 -2
- classiq/evaluators/qmod_node_evaluators/binary_op_evaluation.py +18 -29
- classiq/evaluators/qmod_node_evaluators/min_max_evaluation.py +1 -6
- classiq/evaluators/qmod_node_evaluators/numeric_attrs_utils.py +1 -7
- classiq/evaluators/qmod_node_evaluators/utils.py +6 -3
- classiq/evaluators/qmod_type_inference/quantum_type_comparison.py +52 -0
- classiq/execution/__init__.py +11 -1
- classiq/execution/execution_session.py +1 -1
- classiq/execution/functions/__init__.py +3 -0
- classiq/execution/functions/_logging.py +19 -0
- classiq/execution/functions/constants.py +9 -0
- classiq/execution/functions/parse_provider_backend.py +90 -0
- classiq/execution/functions/sample.py +257 -0
- classiq/execution/jobs.py +122 -5
- classiq/interface/_version.py +1 -1
- classiq/interface/backend/backend_preferences.py +15 -0
- classiq/interface/backend/provider_config/providers/aqt.py +1 -1
- classiq/interface/backend/provider_config/providers/azure.py +1 -2
- classiq/interface/backend/provider_config/providers/ibm.py +1 -1
- classiq/interface/backend/quantum_backend_providers.py +3 -0
- classiq/interface/exceptions.py +0 -42
- classiq/interface/executor/execution_request.py +1 -0
- classiq/interface/executor/quantum_code.py +0 -6
- classiq/interface/executor/result.py +9 -5
- classiq/interface/generator/arith/binary_ops.py +38 -2
- classiq/interface/generator/function_param_list.py +4 -2
- classiq/interface/generator/functions/builtins/internal_operators.py +5 -9
- classiq/interface/generator/functions/classical_type.py +45 -0
- classiq/interface/generator/functions/type_name.py +23 -0
- classiq/interface/generator/generated_circuit_data.py +0 -2
- classiq/interface/generator/generation_request.py +9 -4
- classiq/interface/generator/quantum_program.py +8 -36
- classiq/interface/generator/types/compilation_metadata.py +9 -0
- classiq/interface/hardware.py +1 -0
- classiq/interface/helpers/model_normalizer.py +62 -2
- classiq/interface/helpers/text_utils.py +17 -6
- classiq/interface/interface_version.py +1 -1
- classiq/interface/model/invert.py +15 -0
- classiq/interface/model/model.py +42 -3
- classiq/interface/model/model_visitor.py +4 -2
- classiq/interface/model/quantum_function_call.py +17 -5
- classiq/interface/model/quantum_type.py +21 -0
- classiq/interface/model/statement_block.py +0 -4
- classiq/model_expansions/capturing/captured_vars.py +16 -12
- classiq/model_expansions/function_builder.py +9 -1
- classiq/model_expansions/interpreters/base_interpreter.py +12 -10
- classiq/model_expansions/interpreters/generative_interpreter.py +9 -24
- classiq/model_expansions/quantum_operations/arithmetic/explicit_boolean_expressions.py +1 -0
- classiq/model_expansions/quantum_operations/assignment_result_processor.py +132 -28
- classiq/model_expansions/quantum_operations/bind.py +4 -0
- classiq/model_expansions/quantum_operations/call_emitter.py +5 -35
- classiq/model_expansions/quantum_operations/emitter.py +1 -4
- classiq/model_expansions/quantum_operations/expression_evaluator.py +0 -3
- classiq/model_expansions/visitors/uncomputation_signature_inference.py +15 -47
- classiq/open_library/functions/__init__.py +42 -27
- classiq/open_library/functions/bit_operations.py +30 -0
- classiq/open_library/functions/modular_arithmetics.py +597 -0
- classiq/open_library/functions/qft_space_arithmetics.py +81 -0
- classiq/open_library/functions/state_preparation.py +6 -3
- classiq/open_library/functions/utility_functions.py +22 -3
- classiq/qmod/builtins/functions/__init__.py +9 -0
- classiq/qmod/builtins/functions/arithmetic.py +131 -0
- classiq/qmod/builtins/functions/exponentiation.py +34 -4
- classiq/qmod/builtins/operations.py +30 -41
- classiq/qmod/native/pretty_printer.py +12 -12
- classiq/qmod/pretty_print/pretty_printer.py +11 -15
- classiq/qmod/qmod_parameter.py +4 -0
- classiq/qmod/qmod_variable.py +38 -63
- classiq/qmod/quantum_callable.py +8 -2
- classiq/qmod/quantum_expandable.py +3 -1
- classiq/qmod/quantum_function.py +45 -8
- classiq/qmod/semantics/validation/function_name_collisions_validation.py +7 -4
- classiq/qmod/semantics/validation/model_validation.py +7 -2
- classiq/qmod/symbolic_type.py +4 -2
- classiq/qmod/utilities.py +7 -4
- classiq/synthesis_action/__init__.py +20 -0
- classiq/synthesis_action/actions.py +106 -0
- {classiq-0.100.0.dist-info → classiq-0.104.0.dist-info}/METADATA +1 -1
- {classiq-0.100.0.dist-info → classiq-0.104.0.dist-info}/RECORD +90 -84
- classiq/interface/executor/register_initialization.py +0 -36
- classiq/interface/generator/amplitude_loading.py +0 -103
- classiq/interface/model/quantum_expressions/amplitude_loading_operation.py +0 -77
- classiq/open_library/functions/modular_exponentiation.py +0 -272
- classiq/open_library/functions/qsvt_temp.py +0 -536
- {classiq-0.100.0.dist-info → classiq-0.104.0.dist-info}/WHEEL +0 -0
- {classiq-0.100.0.dist-info → classiq-0.104.0.dist-info}/licenses/LICENSE.txt +0 -0
classiq/interface/exceptions.py
CHANGED
|
@@ -35,14 +35,6 @@ class ClassiqMissingOutputFormatError(ClassiqError):
|
|
|
35
35
|
super().__init__(message=msg)
|
|
36
36
|
|
|
37
37
|
|
|
38
|
-
class ClassiqCombinatorialOptimizationError(ClassiqError):
|
|
39
|
-
pass
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
class ClassiqOracleError(ClassiqError):
|
|
43
|
-
pass
|
|
44
|
-
|
|
45
|
-
|
|
46
38
|
class ClassiqAnalyzerError(ClassiqError):
|
|
47
39
|
pass
|
|
48
40
|
|
|
@@ -57,10 +49,6 @@ class ClassiqAPIError(ClassiqError):
|
|
|
57
49
|
super().__init__(message)
|
|
58
50
|
|
|
59
51
|
|
|
60
|
-
class ClassiqVersionError(ClassiqError):
|
|
61
|
-
pass
|
|
62
|
-
|
|
63
|
-
|
|
64
52
|
class ClassiqValueError(ClassiqError, ValueError):
|
|
65
53
|
pass
|
|
66
54
|
|
|
@@ -77,10 +65,6 @@ class ClassiqIndexError(ClassiqError, IndexError):
|
|
|
77
65
|
pass
|
|
78
66
|
|
|
79
67
|
|
|
80
|
-
class ClassiqWiringError(ClassiqValueError):
|
|
81
|
-
pass
|
|
82
|
-
|
|
83
|
-
|
|
84
68
|
class ClassiqControlError(ClassiqError):
|
|
85
69
|
def __init__(self) -> None:
|
|
86
70
|
message = "Repeated control names, please rename the control states"
|
|
@@ -91,10 +75,6 @@ class ClassiqQRegError(ClassiqValueError):
|
|
|
91
75
|
pass
|
|
92
76
|
|
|
93
77
|
|
|
94
|
-
class ClassiqQFuncError(ClassiqValueError):
|
|
95
|
-
pass
|
|
96
|
-
|
|
97
|
-
|
|
98
78
|
class ClassiqQNNError(ClassiqValueError):
|
|
99
79
|
pass
|
|
100
80
|
|
|
@@ -103,10 +83,6 @@ class ClassiqTorchError(ClassiqQNNError):
|
|
|
103
83
|
pass
|
|
104
84
|
|
|
105
85
|
|
|
106
|
-
class ClassiqChemistryError(ClassiqError):
|
|
107
|
-
pass
|
|
108
|
-
|
|
109
|
-
|
|
110
86
|
class ClassiqAuthenticationError(ClassiqError):
|
|
111
87
|
pass
|
|
112
88
|
|
|
@@ -115,22 +91,10 @@ class ClassiqExpiredTokenError(ClassiqAuthenticationError):
|
|
|
115
91
|
pass
|
|
116
92
|
|
|
117
93
|
|
|
118
|
-
class ClassiqFileNotFoundError(FileNotFoundError):
|
|
119
|
-
pass
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
class ClassiqStateInitializationError(ClassiqError):
|
|
123
|
-
pass
|
|
124
|
-
|
|
125
|
-
|
|
126
94
|
class ClassiqPasswordManagerSelectionError(ClassiqError):
|
|
127
95
|
pass
|
|
128
96
|
|
|
129
97
|
|
|
130
|
-
class ClassiqMismatchIOsError(ClassiqError):
|
|
131
|
-
pass
|
|
132
|
-
|
|
133
|
-
|
|
134
98
|
class ClassiqNotImplementedError(ClassiqError, NotImplementedError):
|
|
135
99
|
pass
|
|
136
100
|
|
|
@@ -171,12 +135,6 @@ class ClassiqCombOptNotSupportedProblemError(ClassiqCombOptError):
|
|
|
171
135
|
pass
|
|
172
136
|
|
|
173
137
|
|
|
174
|
-
class ClassiqExecutorInvalidHamiltonianError(ClassiqCombOptError):
|
|
175
|
-
|
|
176
|
-
def __init__(self) -> None:
|
|
177
|
-
super().__init__("Invalid hamiltonian")
|
|
178
|
-
|
|
179
|
-
|
|
180
138
|
class ClassiqDeprecationWarning(FutureWarning):
|
|
181
139
|
pass
|
|
182
140
|
|
|
@@ -11,7 +11,6 @@ from classiq.interface.backend.ionq.ionq_quantum_program import IonqQuantumCircu
|
|
|
11
11
|
from classiq.interface.backend.pydantic_backend import PydanticArgumentNameType
|
|
12
12
|
from classiq.interface.exceptions import ClassiqValueError
|
|
13
13
|
from classiq.interface.executor.quantum_instruction_set import QuantumInstructionSet
|
|
14
|
-
from classiq.interface.executor.register_initialization import RegisterInitialization
|
|
15
14
|
from classiq.interface.generator.synthesis_metadata.synthesis_execution_data import (
|
|
16
15
|
ExecutionData,
|
|
17
16
|
)
|
|
@@ -19,7 +18,6 @@ from classiq.interface.generator.synthesis_metadata.synthesis_execution_data imp
|
|
|
19
18
|
Arguments = dict[PydanticArgumentNameType, Any]
|
|
20
19
|
MultipleArguments = tuple[Arguments, ...]
|
|
21
20
|
CodeType = str
|
|
22
|
-
RegistersInitialization = dict[str, RegisterInitialization]
|
|
23
21
|
Qubits = tuple[int, ...]
|
|
24
22
|
OutputQubitsMap = dict[str, Qubits]
|
|
25
23
|
|
|
@@ -57,10 +55,6 @@ class QuantumCode(QuantumBaseCode):
|
|
|
57
55
|
default_factory=dict,
|
|
58
56
|
description="The map of outputs to their qubits in the circuit.",
|
|
59
57
|
)
|
|
60
|
-
registers_initialization: RegistersInitialization | None = pydantic.Field(
|
|
61
|
-
default=None,
|
|
62
|
-
description="Initial conditions for the different registers in the circuit.",
|
|
63
|
-
)
|
|
64
58
|
synthesis_execution_data: ExecutionData | None = pydantic.Field(default=None)
|
|
65
59
|
synthesis_execution_arguments: Arguments = pydantic.Field(default_factory=dict)
|
|
66
60
|
model_config = ConfigDict(validate_assignment=True)
|
|
@@ -47,7 +47,7 @@ StateVector: TypeAlias = Optional[dict[str, Complex]]
|
|
|
47
47
|
BITSTRING = "bitstring"
|
|
48
48
|
PROBABILITY = "probability"
|
|
49
49
|
AMPLITUDE = "amplitude"
|
|
50
|
-
|
|
50
|
+
COUNTS = "counts"
|
|
51
51
|
MAGNITUDE = "magnitude"
|
|
52
52
|
PHASE = "phase"
|
|
53
53
|
|
|
@@ -374,7 +374,9 @@ class ExecutionDetails(BaseModel, QmodPyObject):
|
|
|
374
374
|
|
|
375
375
|
for bitstring, count in self.counts.items():
|
|
376
376
|
data[BITSTRING].append(bitstring)
|
|
377
|
-
|
|
377
|
+
# TODO CLS-4767: delete "count"
|
|
378
|
+
data["count"].append(count)
|
|
379
|
+
data[COUNTS].append(count)
|
|
378
380
|
if self.probabilities:
|
|
379
381
|
data[PROBABILITY].append(self.probabilities[bitstring])
|
|
380
382
|
elif self.num_shots:
|
|
@@ -383,7 +385,8 @@ class ExecutionDetails(BaseModel, QmodPyObject):
|
|
|
383
385
|
for name, value in self.parsed_states[bitstring].items():
|
|
384
386
|
data[name].append(value)
|
|
385
387
|
|
|
386
|
-
|
|
388
|
+
# TODO CLS-4767: delete "count"
|
|
389
|
+
final_columns = [COUNTS, "count", PROBABILITY, BITSTRING]
|
|
387
390
|
columns = [
|
|
388
391
|
col for col in data.keys() if col not in final_columns
|
|
389
392
|
] + final_columns
|
|
@@ -419,8 +422,9 @@ class ExecutionDetails(BaseModel, QmodPyObject):
|
|
|
419
422
|
|
|
420
423
|
@functools.cached_property
|
|
421
424
|
def dataframe(self) -> "pd.DataFrame":
|
|
425
|
+
# TODO CLS-4767: remove "count"
|
|
422
426
|
reserved_words = frozenset(
|
|
423
|
-
[BITSTRING, PROBABILITY,
|
|
427
|
+
["count", BITSTRING, PROBABILITY, COUNTS, AMPLITUDE, PHASE, MAGNITUDE]
|
|
424
428
|
)
|
|
425
429
|
_invalid_output_names = reserved_words.intersection(
|
|
426
430
|
self.output_qubits_map.keys()
|
|
@@ -436,7 +440,7 @@ class ExecutionDetails(BaseModel, QmodPyObject):
|
|
|
436
440
|
df = self._counts_df()
|
|
437
441
|
|
|
438
442
|
df.sort_values(
|
|
439
|
-
by=[AMPLITUDE if self.state_vector else
|
|
443
|
+
by=[AMPLITUDE if self.state_vector else COUNTS, BITSTRING],
|
|
440
444
|
inplace=True,
|
|
441
445
|
ascending=[False, True],
|
|
442
446
|
ignore_index=True,
|
|
@@ -29,7 +29,10 @@ from classiq.interface.generator.arith.ast_node_rewrite import (
|
|
|
29
29
|
)
|
|
30
30
|
from classiq.interface.generator.arith.register_user_input import RegisterArithmeticInfo
|
|
31
31
|
from classiq.interface.generator.arith.unary_ops import Negation
|
|
32
|
-
from classiq.interface.generator.function_params import
|
|
32
|
+
from classiq.interface.generator.function_params import (
|
|
33
|
+
FunctionParams,
|
|
34
|
+
get_zero_input_name,
|
|
35
|
+
)
|
|
33
36
|
|
|
34
37
|
from classiq.model_expansions.arithmetic import NumericAttributes
|
|
35
38
|
from classiq.model_expansions.arithmetic_compute_result_attrs import (
|
|
@@ -533,10 +536,43 @@ class Multiplier(BinaryOpWithFloatInputs):
|
|
|
533
536
|
|
|
534
537
|
def garbage_output_size(self) -> pydantic.NonNegativeInt:
|
|
535
538
|
return max(
|
|
536
|
-
0,
|
|
539
|
+
0,
|
|
540
|
+
self.expected_fraction_places() - self.result_register.fraction_places - 1,
|
|
537
541
|
)
|
|
538
542
|
|
|
539
543
|
|
|
544
|
+
class CanonicalMultiplier(FunctionParams):
|
|
545
|
+
left_size: pydantic.PositiveInt
|
|
546
|
+
extend_left: bool
|
|
547
|
+
right_size: pydantic.PositiveInt
|
|
548
|
+
extend_right: bool
|
|
549
|
+
result_size: pydantic.PositiveInt
|
|
550
|
+
trim_result_lsb: bool
|
|
551
|
+
|
|
552
|
+
def _create_ios(self) -> None:
|
|
553
|
+
self._inputs = {
|
|
554
|
+
"left": RegisterArithmeticInfo(size=self.left_size),
|
|
555
|
+
"right": RegisterArithmeticInfo(size=self.right_size),
|
|
556
|
+
"result": RegisterArithmeticInfo(size=self.result_size),
|
|
557
|
+
}
|
|
558
|
+
self._outputs = {**self._inputs}
|
|
559
|
+
|
|
560
|
+
|
|
561
|
+
class CanonicalConstantMultiplier(FunctionParams):
|
|
562
|
+
left: int
|
|
563
|
+
right_size: pydantic.PositiveInt
|
|
564
|
+
extend_right: bool
|
|
565
|
+
result_size: pydantic.PositiveInt
|
|
566
|
+
trim_result_lsb: bool
|
|
567
|
+
|
|
568
|
+
def _create_ios(self) -> None:
|
|
569
|
+
self._inputs = {
|
|
570
|
+
"right": RegisterArithmeticInfo(size=self.right_size),
|
|
571
|
+
"result": RegisterArithmeticInfo(size=self.result_size),
|
|
572
|
+
}
|
|
573
|
+
self._outputs = {**self._inputs}
|
|
574
|
+
|
|
575
|
+
|
|
540
576
|
class Comparator(BinaryOpWithFloatInputs):
|
|
541
577
|
output_size: Literal[1] = 1
|
|
542
578
|
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import itertools
|
|
2
2
|
|
|
3
|
-
from classiq.interface.generator.amplitude_loading import AmplitudeLoading
|
|
4
3
|
from classiq.interface.generator.arith.arithmetic import Arithmetic
|
|
5
4
|
from classiq.interface.generator.arith.binary_ops import (
|
|
6
5
|
Adder,
|
|
7
6
|
BitwiseAnd,
|
|
8
7
|
BitwiseOr,
|
|
9
8
|
BitwiseXor,
|
|
9
|
+
CanonicalConstantMultiplier,
|
|
10
|
+
CanonicalMultiplier,
|
|
10
11
|
Equal,
|
|
11
12
|
GreaterEqual,
|
|
12
13
|
GreaterThan,
|
|
@@ -79,6 +80,8 @@ function_param_library: FunctionParamLibrary = FunctionParamLibrary(
|
|
|
79
80
|
HardwareEfficientAnsatz,
|
|
80
81
|
UnitaryGate,
|
|
81
82
|
Multiplier,
|
|
83
|
+
CanonicalMultiplier,
|
|
84
|
+
CanonicalConstantMultiplier,
|
|
82
85
|
Power,
|
|
83
86
|
Min,
|
|
84
87
|
Max,
|
|
@@ -88,7 +91,6 @@ function_param_library: FunctionParamLibrary = FunctionParamLibrary(
|
|
|
88
91
|
Identity,
|
|
89
92
|
RandomizedBenchmarking,
|
|
90
93
|
UGate,
|
|
91
|
-
AmplitudeLoading,
|
|
92
94
|
HadamardTransform,
|
|
93
95
|
Copy,
|
|
94
96
|
Reset,
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
CTRL_VAR_PREFIX = "ctrl__"
|
|
2
2
|
CONTROL_OPERATOR_NAME = "control"
|
|
3
3
|
SKIP_CONTROL_OPERATOR_NAME = "skip_control"
|
|
4
|
-
|
|
4
|
+
COMPOUND_INVERT_OPERATOR_NAME = "compound_invert"
|
|
5
|
+
SINGLE_CALL_INVERT_OPERATOR_NAME = "single_call_invert"
|
|
5
6
|
REPEAT_OPERATOR_NAME = "iteration"
|
|
6
7
|
CLASSICAL_IF_OPERATOR_NAME = "classical_if"
|
|
7
8
|
POWER_OPERATOR_NAME = "power"
|
|
@@ -9,12 +10,7 @@ UNCOMPUTE_OPERATOR_NAME = "uncompute"
|
|
|
9
10
|
WITHIN_APPLY_NAME = "within_apply"
|
|
10
11
|
BLOCK_OPERATOR_NAME = "block"
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
REPEAT_OPERATOR_NAME,
|
|
16
|
-
POWER_OPERATOR_NAME,
|
|
17
|
-
UNCOMPUTE_OPERATOR_NAME,
|
|
18
|
-
WITHIN_APPLY_NAME,
|
|
19
|
-
BLOCK_OPERATOR_NAME,
|
|
13
|
+
INVERT_OPERATOR_NAMES = {
|
|
14
|
+
COMPOUND_INVERT_OPERATOR_NAME,
|
|
15
|
+
SINGLE_CALL_INVERT_OPERATOR_NAME,
|
|
20
16
|
}
|
|
@@ -61,6 +61,10 @@ class ClassicalType(HashableASTNode):
|
|
|
61
61
|
def raw_qmod_type_name(self) -> str:
|
|
62
62
|
return self.qmod_type_name
|
|
63
63
|
|
|
64
|
+
@property
|
|
65
|
+
def python_type_name(self) -> str:
|
|
66
|
+
raise NotImplementedError
|
|
67
|
+
|
|
64
68
|
@property
|
|
65
69
|
def expressions(self) -> list[Expression]:
|
|
66
70
|
return []
|
|
@@ -76,6 +80,9 @@ class ClassicalType(HashableASTNode):
|
|
|
76
80
|
def without_symbolic_attributes(self) -> Self:
|
|
77
81
|
return self
|
|
78
82
|
|
|
83
|
+
def get_compile_time_attributes(self, path_expr_prefix: str) -> dict[str, Any]:
|
|
84
|
+
return {}
|
|
85
|
+
|
|
79
86
|
|
|
80
87
|
class Integer(ClassicalType):
|
|
81
88
|
kind: Literal["int"]
|
|
@@ -89,6 +96,10 @@ class Integer(ClassicalType):
|
|
|
89
96
|
def qmod_type_name(self) -> str:
|
|
90
97
|
return "CInt"
|
|
91
98
|
|
|
99
|
+
@property
|
|
100
|
+
def python_type_name(self) -> str:
|
|
101
|
+
return "int"
|
|
102
|
+
|
|
92
103
|
|
|
93
104
|
class Real(ClassicalType):
|
|
94
105
|
kind: Literal["real"]
|
|
@@ -102,6 +113,10 @@ class Real(ClassicalType):
|
|
|
102
113
|
def qmod_type_name(self) -> str:
|
|
103
114
|
return "CReal"
|
|
104
115
|
|
|
116
|
+
@property
|
|
117
|
+
def python_type_name(self) -> str:
|
|
118
|
+
return "float"
|
|
119
|
+
|
|
105
120
|
|
|
106
121
|
class Bool(ClassicalType):
|
|
107
122
|
kind: Literal["bool"]
|
|
@@ -115,6 +130,10 @@ class Bool(ClassicalType):
|
|
|
115
130
|
def qmod_type_name(self) -> str:
|
|
116
131
|
return "CBool"
|
|
117
132
|
|
|
133
|
+
@property
|
|
134
|
+
def python_type_name(self) -> str:
|
|
135
|
+
return "bool"
|
|
136
|
+
|
|
118
137
|
|
|
119
138
|
class StructMetaType(ClassicalType):
|
|
120
139
|
kind: Literal["type_proxy"]
|
|
@@ -201,6 +220,10 @@ class ClassicalArray(ClassicalType):
|
|
|
201
220
|
def raw_qmod_type_name(self) -> str:
|
|
202
221
|
return "CArray"
|
|
203
222
|
|
|
223
|
+
@property
|
|
224
|
+
def python_type_name(self) -> str:
|
|
225
|
+
return f"list[{self.element_type.python_type_name}]"
|
|
226
|
+
|
|
204
227
|
def without_symbolic_attributes(self) -> "ClassicalArray":
|
|
205
228
|
length = (
|
|
206
229
|
None
|
|
@@ -213,6 +236,14 @@ class ClassicalArray(ClassicalType):
|
|
|
213
236
|
element_type=self.element_type.without_symbolic_attributes(), length=length
|
|
214
237
|
)
|
|
215
238
|
|
|
239
|
+
def get_compile_time_attributes(self, path_expr_prefix: str) -> dict[str, Any]:
|
|
240
|
+
attrs: dict[str, Any] = {}
|
|
241
|
+
if self.has_constant_length:
|
|
242
|
+
attrs[f"{path_expr_prefix}.len"] = self.length_value
|
|
243
|
+
return attrs | self.element_type.get_compile_time_attributes(
|
|
244
|
+
f"{path_expr_prefix}[0]"
|
|
245
|
+
)
|
|
246
|
+
|
|
216
247
|
|
|
217
248
|
class ClassicalTuple(ClassicalType):
|
|
218
249
|
kind: Literal["tuple"]
|
|
@@ -283,6 +314,13 @@ class ClassicalTuple(ClassicalType):
|
|
|
283
314
|
def raw_qmod_type_name(self) -> str:
|
|
284
315
|
return "CArray"
|
|
285
316
|
|
|
317
|
+
@property
|
|
318
|
+
def python_type_name(self) -> str:
|
|
319
|
+
raw_type = self.get_raw_type(preserve_length=True)
|
|
320
|
+
if isinstance(raw_type, ClassicalTuple):
|
|
321
|
+
return "list"
|
|
322
|
+
return raw_type.python_type_name
|
|
323
|
+
|
|
286
324
|
def without_symbolic_attributes(self) -> "ClassicalTuple":
|
|
287
325
|
return ClassicalTuple(
|
|
288
326
|
element_types=[
|
|
@@ -291,6 +329,13 @@ class ClassicalTuple(ClassicalType):
|
|
|
291
329
|
]
|
|
292
330
|
)
|
|
293
331
|
|
|
332
|
+
def get_compile_time_attributes(self, path_expr_prefix: str) -> dict[str, Any]:
|
|
333
|
+
raw_type = self.get_raw_type(preserve_length=True)
|
|
334
|
+
attrs = {f"{path_expr_prefix}.len": len(self.element_types)}
|
|
335
|
+
if isinstance(raw_type, ClassicalTuple):
|
|
336
|
+
return attrs
|
|
337
|
+
return attrs | raw_type.get_compile_time_attributes(path_expr_prefix)
|
|
338
|
+
|
|
294
339
|
|
|
295
340
|
class OpaqueHandle(ClassicalType):
|
|
296
341
|
pass
|
|
@@ -60,6 +60,10 @@ class TypeName(ClassicalType, QuantumType):
|
|
|
60
60
|
def qmod_type_name(self) -> str:
|
|
61
61
|
return self.name
|
|
62
62
|
|
|
63
|
+
@property
|
|
64
|
+
def python_type_name(self) -> str:
|
|
65
|
+
return self.name
|
|
66
|
+
|
|
63
67
|
@property
|
|
64
68
|
def type_name(self) -> str:
|
|
65
69
|
return self.name
|
|
@@ -202,6 +206,25 @@ class TypeName(ClassicalType, QuantumType):
|
|
|
202
206
|
return type_name
|
|
203
207
|
return self
|
|
204
208
|
|
|
209
|
+
def get_compile_time_attributes(self, path_expr_prefix: str) -> dict[str, Any]:
|
|
210
|
+
attrs: dict[str, Any] = {}
|
|
211
|
+
if self.has_fields:
|
|
212
|
+
for field_name, field_type in self.fields.items():
|
|
213
|
+
field_prefix = f"{path_expr_prefix}.{field_name}"
|
|
214
|
+
attrs[field_prefix] = field_type.get_compile_time_attributes(
|
|
215
|
+
field_prefix
|
|
216
|
+
)
|
|
217
|
+
elif self.has_classical_struct_decl:
|
|
218
|
+
for (
|
|
219
|
+
field_name,
|
|
220
|
+
classical_field_type,
|
|
221
|
+
) in self.classical_struct_decl.variables.items():
|
|
222
|
+
field_prefix = f"{path_expr_prefix}.{field_name}"
|
|
223
|
+
attrs[field_prefix] = classical_field_type.get_compile_time_attributes(
|
|
224
|
+
field_prefix
|
|
225
|
+
)
|
|
226
|
+
return attrs
|
|
227
|
+
|
|
205
228
|
|
|
206
229
|
class Enum(TypeName):
|
|
207
230
|
pass
|
|
@@ -140,7 +140,6 @@ class StatementType(StrEnum):
|
|
|
140
140
|
WITHIN = "within"
|
|
141
141
|
APPLY = "apply"
|
|
142
142
|
ASSIGN = "assign"
|
|
143
|
-
ASSIGN_AMPLITUDE = "assign amplitude"
|
|
144
143
|
PHASE = "phase"
|
|
145
144
|
INPLACE_XOR = "inplace xor"
|
|
146
145
|
INPLACE_ADD = "inplace add"
|
|
@@ -163,7 +162,6 @@ STATEMENTS_NAME: dict[str, StatementType] = {
|
|
|
163
162
|
"Uncompute": StatementType.WITHIN,
|
|
164
163
|
ArithmeticOperationKind.Assignment.value: StatementType.ASSIGN,
|
|
165
164
|
"InplaceBinaryOperation": StatementType.ASSIGN,
|
|
166
|
-
"AmplitudeLoadingOperation": StatementType.ASSIGN_AMPLITUDE,
|
|
167
165
|
"PhaseOperation": StatementType.PHASE,
|
|
168
166
|
ArithmeticOperationKind.InplaceXor.value: StatementType.INPLACE_XOR,
|
|
169
167
|
ArithmeticOperationKind.InplaceAdd.value: StatementType.INPLACE_ADD,
|
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
from datetime import datetime
|
|
2
2
|
|
|
3
|
-
from pydantic import Field
|
|
3
|
+
from pydantic import ConfigDict, Field
|
|
4
4
|
|
|
5
5
|
from classiq.interface.helpers.versioned_model import VersionedModel
|
|
6
6
|
from classiq.interface.jobs import JobStatus
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
class
|
|
9
|
+
class SynthesisActionDetails(VersionedModel):
|
|
10
|
+
"""
|
|
11
|
+
Details of a synthesis user action.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
model_config = ConfigDict(frozen=True)
|
|
10
15
|
id: str
|
|
11
16
|
|
|
12
17
|
name: str | None = Field(default=None)
|
|
@@ -31,5 +36,5 @@ class SynthesisJobDetails(VersionedModel):
|
|
|
31
36
|
max_gate_count: int | None = Field(default=None)
|
|
32
37
|
|
|
33
38
|
|
|
34
|
-
class
|
|
35
|
-
results: list[
|
|
39
|
+
class SynthesisActionsQueryResults(VersionedModel):
|
|
40
|
+
results: list[SynthesisActionDetails]
|
|
@@ -10,12 +10,10 @@ from classiq.interface.compression_utils import decompress
|
|
|
10
10
|
from classiq.interface.exceptions import (
|
|
11
11
|
ClassiqDeprecationWarning,
|
|
12
12
|
ClassiqMissingOutputFormatError,
|
|
13
|
-
ClassiqStateInitializationError,
|
|
14
13
|
)
|
|
15
14
|
from classiq.interface.execution.primitives import PrimitivesInput
|
|
16
15
|
from classiq.interface.executor import quantum_code
|
|
17
16
|
from classiq.interface.executor.quantum_instruction_set import QuantumInstructionSet
|
|
18
|
-
from classiq.interface.executor.register_initialization import RegisterInitialization
|
|
19
17
|
from classiq.interface.generator.circuit_code.circuit_code import CircuitCodeInterface
|
|
20
18
|
from classiq.interface.generator.circuit_code.types_and_constants import (
|
|
21
19
|
INSTRUCTION_SET_TO_FORMAT,
|
|
@@ -29,9 +27,9 @@ from classiq.interface.generator.hardware.hardware_data import SynthesisHardware
|
|
|
29
27
|
from classiq.interface.generator.model.model import ExecutionModel
|
|
30
28
|
from classiq.interface.helpers.versioned_model import VersionedModel
|
|
31
29
|
from classiq.interface.ide.visual_model import CircuitMetrics
|
|
30
|
+
from classiq.interface.model.model import Model
|
|
32
31
|
|
|
33
32
|
RegisterName: TypeAlias = str
|
|
34
|
-
InitialConditions: TypeAlias = dict[RegisterName, int]
|
|
35
33
|
|
|
36
34
|
|
|
37
35
|
class TranspiledCircuitData(CircuitCodeInterface):
|
|
@@ -56,7 +54,6 @@ def _get_formatted_utc_current_time() -> str:
|
|
|
56
54
|
|
|
57
55
|
class QuantumProgram(VersionedModel, CircuitCodeInterface):
|
|
58
56
|
hardware_data: SynthesisHardwareData
|
|
59
|
-
initial_values: InitialConditions | None = pydantic.Field(default=None)
|
|
60
57
|
data: GeneratedCircuitData
|
|
61
58
|
model: ExecutionModel
|
|
62
59
|
transpiled_circuit: TranspiledCircuitData | None = pydantic.Field(default=None)
|
|
@@ -65,7 +62,7 @@ class QuantumProgram(VersionedModel, CircuitCodeInterface):
|
|
|
65
62
|
program_id: str = pydantic.Field(default_factory=get_uuid_as_str)
|
|
66
63
|
execution_primitives_input: PrimitivesInput | None = pydantic.Field(default=None)
|
|
67
64
|
synthesis_warnings: list[str] | None = pydantic.Field(default=None)
|
|
68
|
-
|
|
65
|
+
compiled_qmod: Model | None = pydantic.Field(default=None)
|
|
69
66
|
|
|
70
67
|
def __str__(self) -> str:
|
|
71
68
|
return self.model_dump_json(indent=2)
|
|
@@ -85,10 +82,8 @@ class QuantumProgram(VersionedModel, CircuitCodeInterface):
|
|
|
85
82
|
|
|
86
83
|
def to_program(
|
|
87
84
|
self,
|
|
88
|
-
initial_values: InitialConditions | None = None,
|
|
89
85
|
instruction_set: QuantumInstructionSet | None = None,
|
|
90
86
|
) -> quantum_code.QuantumCode:
|
|
91
|
-
initial_values = initial_values or self.initial_values
|
|
92
87
|
if instruction_set is not None:
|
|
93
88
|
code, syntax = (
|
|
94
89
|
self.program_circuit.get_code(instruction_set),
|
|
@@ -97,40 +92,17 @@ class QuantumProgram(VersionedModel, CircuitCodeInterface):
|
|
|
97
92
|
else:
|
|
98
93
|
code, syntax = self._default_program_code()
|
|
99
94
|
|
|
100
|
-
if initial_values is not None:
|
|
101
|
-
registers_initialization = self.get_registers_initialization(
|
|
102
|
-
initial_values=initial_values
|
|
103
|
-
)
|
|
104
|
-
else:
|
|
105
|
-
registers_initialization = None
|
|
106
95
|
return quantum_code.QuantumCode(
|
|
107
96
|
code=code,
|
|
108
97
|
syntax=syntax,
|
|
109
|
-
output_qubits_map=
|
|
110
|
-
|
|
98
|
+
output_qubits_map=(
|
|
99
|
+
self.data.qubit_mapping.physical_outputs
|
|
100
|
+
if self._can_use_transpiled_code
|
|
101
|
+
else self.data.qubit_mapping.logical_outputs
|
|
102
|
+
),
|
|
111
103
|
synthesis_execution_data=self.data.execution_data,
|
|
112
104
|
)
|
|
113
105
|
|
|
114
|
-
def _get_initialization_qubits(self, name: str) -> tuple[int, ...]:
|
|
115
|
-
qubits = self.data.qubit_mapping.logical_inputs.get(name)
|
|
116
|
-
if qubits is None:
|
|
117
|
-
raise ClassiqStateInitializationError(
|
|
118
|
-
f"Cannot initialize register {name}, it does not appear in circuit inputs"
|
|
119
|
-
)
|
|
120
|
-
return qubits
|
|
121
|
-
|
|
122
|
-
def get_registers_initialization(
|
|
123
|
-
self, initial_values: InitialConditions
|
|
124
|
-
) -> dict[RegisterName, RegisterInitialization]:
|
|
125
|
-
return {
|
|
126
|
-
name: RegisterInitialization(
|
|
127
|
-
name=name,
|
|
128
|
-
qubits=list(self._get_initialization_qubits(name)),
|
|
129
|
-
initial_condition=init_value,
|
|
130
|
-
)
|
|
131
|
-
for name, init_value in initial_values.items()
|
|
132
|
-
}
|
|
133
|
-
|
|
134
106
|
def save_results(self, filename: str | Path | None = None) -> None:
|
|
135
107
|
"""
|
|
136
108
|
Saves quantum program results as json into a file.
|
|
@@ -148,7 +120,7 @@ class QuantumProgram(VersionedModel, CircuitCodeInterface):
|
|
|
148
120
|
|
|
149
121
|
@property
|
|
150
122
|
def _can_use_transpiled_code(self) -> bool:
|
|
151
|
-
return (
|
|
123
|
+
return self.transpiled_circuit is not None and (
|
|
152
124
|
self.data.execution_data is None
|
|
153
125
|
or not self.data.execution_data.function_execution
|
|
154
126
|
)
|
|
@@ -5,6 +5,7 @@ class CompilationMetadata(BaseModel):
|
|
|
5
5
|
should_synthesize_separately: bool = Field(default=False)
|
|
6
6
|
occurrences_number: NonNegativeInt = Field(default=0)
|
|
7
7
|
_occupation_number: NonNegativeInt = PrivateAttr(default=0)
|
|
8
|
+
_required_clean_qubit: NonNegativeInt = PrivateAttr(default=0)
|
|
8
9
|
disable_perm_check: bool = Field(default=False)
|
|
9
10
|
disable_const_checks: list[str] | bool = Field(default=False)
|
|
10
11
|
|
|
@@ -16,6 +17,14 @@ class CompilationMetadata(BaseModel):
|
|
|
16
17
|
def occupation_number(self, value: NonNegativeInt) -> None:
|
|
17
18
|
self._occupation_number = value
|
|
18
19
|
|
|
20
|
+
@property
|
|
21
|
+
def required_clean_qubit(self) -> NonNegativeInt:
|
|
22
|
+
return self._required_clean_qubit
|
|
23
|
+
|
|
24
|
+
@required_clean_qubit.setter
|
|
25
|
+
def required_clean_qubit(self, value: NonNegativeInt) -> None:
|
|
26
|
+
self._required_clean_qubit = value
|
|
27
|
+
|
|
19
28
|
@property
|
|
20
29
|
def has_user_directives(self) -> bool:
|
|
21
30
|
return bool(self.disable_perm_check or self.disable_const_checks)
|