classiq 0.79.1__py3-none-any.whl → 0.80.1__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.
Files changed (46) hide show
  1. classiq/__init__.py +7 -0
  2. classiq/_internals/api_wrapper.py +95 -19
  3. classiq/analyzer/show_interactive_hack.py +63 -48
  4. classiq/applications/chemistry/chemistry_model_constructor.py +1 -1
  5. classiq/applications/combinatorial_optimization/combinatorial_optimization_model_constructor.py +3 -3
  6. classiq/interface/_version.py +1 -1
  7. classiq/interface/analyzer/result.py +1 -1
  8. classiq/interface/chemistry/operator.py +3 -8
  9. classiq/interface/executor/quantum_program_params.py +18 -0
  10. classiq/interface/generator/application_apis/chemistry_declarations.py +3 -3
  11. classiq/interface/generator/application_apis/combinatorial_optimization_declarations.py +3 -3
  12. classiq/interface/generator/application_apis/entangler_declarations.py +3 -3
  13. classiq/interface/generator/arith/number_utils.py +8 -0
  14. classiq/interface/generator/expressions/proxies/classical/utils.py +8 -3
  15. classiq/interface/generator/functions/classical_type.py +63 -7
  16. classiq/interface/generator/generated_circuit_data.py +10 -1
  17. classiq/interface/helpers/custom_pydantic_types.py +2 -3
  18. classiq/interface/model/allocate.py +6 -0
  19. classiq/interface/model/quantum_type.py +26 -5
  20. classiq/interface/server/routes.py +6 -0
  21. classiq/model_expansions/atomic_expression_functions_defs.py +9 -1
  22. classiq/model_expansions/capturing/captured_vars.py +1 -1
  23. classiq/model_expansions/evaluators/classical_type_inference.py +39 -27
  24. classiq/model_expansions/evaluators/parameter_types.py +65 -3
  25. classiq/model_expansions/interpreters/frontend_generative_interpreter.py +1 -1
  26. classiq/model_expansions/quantum_operations/allocate.py +121 -34
  27. classiq/model_expansions/quantum_operations/call_emitter.py +1 -1
  28. classiq/model_expansions/scope.py +1 -2
  29. classiq/open_library/functions/__init__.py +2 -0
  30. classiq/open_library/functions/state_preparation.py +86 -3
  31. classiq/qmod/builtins/classical_execution_primitives.py +2 -4
  32. classiq/qmod/builtins/functions/__init__.py +3 -0
  33. classiq/qmod/builtins/functions/arithmetic.py +21 -1
  34. classiq/qmod/builtins/functions/exponentiation.py +24 -0
  35. classiq/qmod/builtins/operations.py +32 -2
  36. classiq/qmod/builtins/structs.py +47 -1
  37. classiq/qmod/native/pretty_printer.py +15 -6
  38. classiq/qmod/pretty_print/pretty_printer.py +15 -6
  39. classiq/qmod/python_classical_type.py +4 -4
  40. classiq/qmod/qmod_parameter.py +5 -1
  41. classiq/qmod/semantics/validation/main_validation.py +5 -0
  42. classiq/quantum_program.py +69 -0
  43. {classiq-0.79.1.dist-info → classiq-0.80.1.dist-info}/METADATA +1 -1
  44. {classiq-0.79.1.dist-info → classiq-0.80.1.dist-info}/RECORD +46 -44
  45. {classiq-0.79.1.dist-info → classiq-0.80.1.dist-info}/WHEEL +1 -1
  46. /classiq/{model_expansions/utils → interface/helpers}/text_utils.py +0 -0
classiq/__init__.py CHANGED
@@ -38,6 +38,8 @@ from classiq.applications.hamiltonian.pauli_decomposition import (
38
38
  hamiltonian_to_matrix,
39
39
  matrix_to_hamiltonian,
40
40
  )
41
+ from classiq.execution import * # noqa: F403
42
+ from classiq.execution import __all__ as _execution_all
41
43
  from classiq.executor import (
42
44
  execute,
43
45
  execute_async,
@@ -47,6 +49,7 @@ from classiq.open_library import * # noqa: F403
47
49
  from classiq.open_library import __all__ as _open_library_all
48
50
  from classiq.qmod import * # noqa: F403
49
51
  from classiq.qmod import __all__ as _qmod_all
52
+ from classiq.quantum_program import ExecutionParams, assign_parameters, transpile
50
53
  from classiq.synthesis import (
51
54
  quantum_program_from_qasm,
52
55
  quantum_program_from_qasm_async,
@@ -87,8 +90,10 @@ __all__ = (
87
90
  "RegisterArithmeticInfo",
88
91
  "ControlState",
89
92
  "Analyzer",
93
+ "ExecutionParams",
90
94
  "QuantumProgram",
91
95
  "authenticate",
96
+ "assign_parameters",
92
97
  "synthesize",
93
98
  "synthesize_async",
94
99
  "execute",
@@ -96,6 +101,7 @@ __all__ = (
96
101
  "set_preferences",
97
102
  "set_constraints",
98
103
  "set_execution_preferences",
104
+ "transpile",
99
105
  "update_preferences",
100
106
  "update_constraints",
101
107
  "update_execution_preferences",
@@ -110,6 +116,7 @@ __all__ = (
110
116
  + _sub_modules
111
117
  + _application_constructors_all
112
118
  + _qmod_all
119
+ + _execution_all
113
120
  + _open_library_all
114
121
  )
115
122
 
@@ -23,7 +23,11 @@ from classiq.interface.execution.iqcc import (
23
23
  IQCCProbeAuthResponse,
24
24
  )
25
25
  from classiq.interface.execution.primitives import PrimitivesInput
26
- from classiq.interface.executor import execution_request
26
+ from classiq.interface.executor import execution_request, quantum_program_params
27
+ from classiq.interface.executor.quantum_program_params import (
28
+ ParameterAssignmentsParams,
29
+ TranspilationParams,
30
+ )
27
31
  from classiq.interface.executor.user_budget import UserBudget
28
32
  from classiq.interface.generator import quantum_program as generator_result
29
33
  from classiq.interface.hardware import HardwareInformation, Provider
@@ -112,17 +116,58 @@ class ApiWrapper:
112
116
  raise ClassiqValueError(f"Unexpected returned value: {res}")
113
117
  return res
114
118
 
119
+ @classmethod
120
+ async def _call_job_and_poll(
121
+ cls,
122
+ url: str,
123
+ job_input: pydantic.BaseModel,
124
+ result_type: type[ResultType],
125
+ http_client: Optional[httpx.AsyncClient],
126
+ ) -> ResultType:
127
+ poller = JobPoller(base_url=url)
128
+ result = await poller.run_pydantic(
129
+ job_input, timeout_sec=None, http_client=http_client
130
+ )
131
+ return _parse_job_response(result, result_type)
132
+
115
133
  @classmethod
116
134
  async def call_generation_task(
117
135
  cls,
118
136
  model: Model,
119
137
  http_client: Optional[httpx.AsyncClient] = None,
120
138
  ) -> generator_result.QuantumProgram:
121
- poller = JobPoller(base_url=routes.TASKS_GENERATE_FULL_PATH)
122
- result = await poller.run_pydantic(
123
- model, timeout_sec=None, http_client=http_client
139
+ return await cls._call_job_and_poll(
140
+ routes.TASKS_GENERATE_FULL_PATH,
141
+ model,
142
+ generator_result.QuantumProgram,
143
+ http_client,
144
+ )
145
+
146
+ @classmethod
147
+ async def call_transpilation_task(
148
+ cls,
149
+ params: TranspilationParams,
150
+ http_client: Optional[httpx.AsyncClient] = None,
151
+ ) -> generator_result.QuantumProgram:
152
+ return await cls._call_job_and_poll(
153
+ routes.TRANSPILATION_FULL_PATH,
154
+ params,
155
+ generator_result.QuantumProgram,
156
+ http_client,
157
+ )
158
+
159
+ @classmethod
160
+ async def call_assign_parameters_task(
161
+ cls,
162
+ params: ParameterAssignmentsParams,
163
+ http_client: Optional[httpx.AsyncClient] = None,
164
+ ) -> generator_result.QuantumProgram:
165
+ return await cls._call_job_and_poll(
166
+ routes.ASSIGN_PARAMETERS_FULL_PATH,
167
+ params,
168
+ generator_result.QuantumProgram,
169
+ http_client,
124
170
  )
125
- return _parse_job_response(result, generator_result.QuantumProgram)
126
171
 
127
172
  @classmethod
128
173
  async def call_get_visual_model(
@@ -143,11 +188,12 @@ class ApiWrapper:
143
188
  circuit: generator_result.QuantumProgram,
144
189
  http_client: Optional[httpx.AsyncClient] = None,
145
190
  ) -> ProgramVisualModel:
146
- poller = JobPoller(base_url=routes.TASKS_VISUAL_MODEL_FULL_PATH)
147
- result = await poller.run_pydantic(
148
- circuit, timeout_sec=None, http_client=http_client
191
+ return await cls._call_job_and_poll(
192
+ routes.TASKS_VISUAL_MODEL_FULL_PATH,
193
+ circuit,
194
+ ProgramVisualModel,
195
+ http_client,
149
196
  )
150
- return _parse_job_response(result, ProgramVisualModel)
151
197
 
152
198
  @classmethod
153
199
  async def call_create_execution_session(
@@ -193,6 +239,36 @@ class ApiWrapper:
193
239
  exclude={"debug_info"},
194
240
  )
195
241
 
242
+ @classmethod
243
+ async def transpile_quantum_program(
244
+ cls,
245
+ params: quantum_program_params.TranspilationParams,
246
+ http_client: Optional[httpx.AsyncClient] = None,
247
+ ) -> generator_result.QuantumProgram:
248
+ data = await cls._call_task_pydantic(
249
+ http_method=HTTPMethod.POST,
250
+ url=routes.TRANSPILATION_FULL_PATH,
251
+ model=params,
252
+ http_client=http_client,
253
+ exclude={"debug_info"},
254
+ )
255
+ return generator_result.QuantumProgram.model_validate(data)
256
+
257
+ @classmethod
258
+ async def assign_parameters_quantum_program(
259
+ cls,
260
+ params: quantum_program_params.ParameterAssignmentsParams,
261
+ http_client: Optional[httpx.AsyncClient] = None,
262
+ ) -> generator_result.QuantumProgram:
263
+ data = await cls._call_task_pydantic(
264
+ http_method=HTTPMethod.POST,
265
+ url=routes.ASSIGN_PARAMETERS_FULL_PATH,
266
+ model=params,
267
+ http_client=http_client,
268
+ exclude={"debug_info"},
269
+ )
270
+ return generator_result.QuantumProgram.model_validate(data)
271
+
196
272
  @classmethod
197
273
  async def call_execute_execution_input(
198
274
  cls,
@@ -374,11 +450,12 @@ class ApiWrapper:
374
450
  params: analysis_params.AnalysisHardwareListParams,
375
451
  http_client: Optional[httpx.AsyncClient] = None,
376
452
  ) -> analysis_result.GraphResult:
377
- poller = JobPoller(base_url=routes.ANALYZER_HC_TABLE_GRAPH_FULL_PATH)
378
- result = await poller.run_pydantic(
379
- params, timeout_sec=None, http_client=http_client
453
+ return await cls._call_job_and_poll(
454
+ routes.ANALYZER_HC_TABLE_GRAPH_FULL_PATH,
455
+ params,
456
+ analysis_result.GraphResult,
457
+ http_client,
380
458
  )
381
- return _parse_job_response(result, analysis_result.GraphResult)
382
459
 
383
460
  @classmethod
384
461
  async def call_available_devices_task(
@@ -434,13 +511,12 @@ class ApiWrapper:
434
511
  problem: ground_state_problem.CHEMISTRY_PROBLEMS_TYPE,
435
512
  http_client: Optional[httpx.AsyncClient] = None,
436
513
  ) -> operator.PauliOperator:
437
- poller = JobPoller(
438
- base_url=routes.GENERATE_HAMILTONIAN_FULL_PATH,
439
- )
440
- result = await poller.run_pydantic(
441
- problem, timeout_sec=None, http_client=http_client
514
+ return await cls._call_job_and_poll(
515
+ routes.GENERATE_HAMILTONIAN_FULL_PATH,
516
+ problem,
517
+ operator.PauliOperator,
518
+ http_client,
442
519
  )
443
- return _parse_job_response(result, operator.PauliOperator)
444
520
 
445
521
  @classmethod
446
522
  async def call_iqcc_init_auth(
@@ -1,8 +1,11 @@
1
1
  import os
2
+ import subprocess
2
3
  import webbrowser
3
- from typing import Callable, Union
4
+ from collections.abc import Awaitable, Callable
5
+ from tempfile import NamedTemporaryFile
4
6
  from urllib.parse import urljoin
5
7
 
8
+ from classiq.interface.analyzer.result import DataID
6
9
  from classiq.interface.exceptions import ClassiqAnalyzerVisualizationError
7
10
  from classiq.interface.generator.model.preferences.preferences import QuantumFormat
8
11
  from classiq.interface.generator.quantum_program import QuantumProgram
@@ -10,12 +13,12 @@ from classiq.interface.generator.quantum_program import QuantumProgram
10
13
  from classiq._internals.api_wrapper import ApiWrapper
11
14
  from classiq._internals.async_utils import is_notebook, syncify_function
12
15
  from classiq.analyzer.url_utils import circuit_page_uri, client_ide_base_url
13
- from classiq.visualization import (
14
- SerializedVisualModel,
15
- visualize_async,
16
- )
16
+ from classiq.visualization import visualize_async
17
17
 
18
- VisualizationRenderer = Callable[[SerializedVisualModel, str], None]
18
+ VisualizationRenderer = Callable[[DataID, QuantumProgram], Awaitable[None]]
19
+
20
+ # In Classiq Studio (openvscode env) we use this command to open files
21
+ VSCODE_COMMAND = "code"
19
22
 
20
23
 
21
24
  def is_classiq_studio() -> bool:
@@ -24,38 +27,61 @@ def is_classiq_studio() -> bool:
24
27
  return bool(os.environ.get("OPENVSCODE"))
25
28
 
26
29
 
27
- def get_visualization_renderer() -> Union[VisualizationRenderer, None]:
28
- # Skip non-interactive environments
29
- if not is_notebook():
30
- return None
31
- # Ideally, we should check if a notebook renderer is available to handle custom
32
- # mime type, or at least if the Classiq vscode extension is installed.
30
+ def get_app_url(data_id: DataID, circuit: QuantumProgram) -> str:
31
+ return urljoin(
32
+ client_ide_base_url(),
33
+ circuit_page_uri(circuit_id=data_id.id, circuit_version=circuit.version),
34
+ )
35
+
36
+
37
+ async def ide_renderer(data_id: DataID, circuit: QuantumProgram) -> None:
38
+ app_url = get_app_url(data_id, circuit)
39
+ webbrowser.open_new_tab(app_url)
40
+
41
+
42
+ async def editor_renderer(data_id: DataID, circuit: QuantumProgram) -> None:
43
+ with NamedTemporaryFile(
44
+ delete=False, prefix=f"{data_id.id}-", suffix=".qprog", mode="w"
45
+ ) as file:
46
+ analyzer_data = await ApiWrapper.get_analyzer_app_data(data_id)
47
+ file.write(analyzer_data.model_dump_json())
48
+ subprocess.run([VSCODE_COMMAND, file.name])
49
+
50
+
51
+ async def notebook_renderer(data_id: DataID, circuit: QuantumProgram) -> None:
52
+ from IPython.display import display # type: ignore[import]
53
+
54
+ visual_model = await visualize_async(data_id)
55
+ app_url = get_app_url(data_id, circuit)
56
+ display(
57
+ {
58
+ # Attempt to handle by notebook renderer from Classiq vscode extension
59
+ "application/vnd.classiq+qviz": visual_model,
60
+ # Fallback to IDE link display when no extension available.
61
+ # Shouldn't normally happen.
62
+ # Otherwise, is_classiq_studio detection is not correct.
63
+ "text/plain": app_url,
64
+ },
65
+ raw=True,
66
+ metadata={
67
+ "url": app_url,
68
+ },
69
+ )
70
+
71
+
72
+ def get_visualization_renderer() -> VisualizationRenderer:
73
+ # Ideally, we should check if a registered custom mime type handler is available,
74
+ # or at least if the Classiq vscode extension is installed.
33
75
  # There's no such capabilities in IPython, so we make assumption from a fact that
34
76
  # it's a Classiq Studio env.
35
77
  # (Studio always has the extension, and the extension always supports mime type).
36
78
  if not is_classiq_studio():
37
- return None
38
- try:
39
- # Must be available since is_notebook passed
40
- from IPython.display import display # type: ignore[import]
41
- except ImportError:
42
- # Just in case it failed anyway, fallback to IDE link open
43
- return None
44
-
45
- def renderer(visual_model: SerializedVisualModel, fallback: str) -> None:
46
- display(
47
- {
48
- # Attempt to handle by notebook renderer from Classiq vscode extension
49
- "application/vnd.classiq+qviz": visual_model,
50
- # Fallback to IDE link display when no extension available.
51
- # Shouldn't normally happen.
52
- # Otherwise, is_classiq_studio detection is not correct.
53
- "text/plain": fallback,
54
- },
55
- raw=True,
56
- )
57
-
58
- return renderer
79
+ return ide_renderer
80
+ # For non-interactive environments, write a temporary file and open it
81
+ if not is_notebook():
82
+ return editor_renderer
83
+ # For interactive notebooks, visualize and render as inline content
84
+ return notebook_renderer
59
85
 
60
86
 
61
87
  async def handle_remote_app(circuit: QuantumProgram, display_url: bool = True) -> None:
@@ -66,23 +92,12 @@ async def handle_remote_app(circuit: QuantumProgram, display_url: bool = True) -
66
92
  "synthesis preferences"
67
93
  )
68
94
  circuit_dataid = await ApiWrapper.call_analyzer_app(circuit)
69
- app_url = urljoin(
70
- client_ide_base_url(),
71
- circuit_page_uri(circuit_id=circuit_dataid.id, circuit_version=circuit.version),
72
- )
73
- link_label = f"Quantum program link: {app_url}"
74
95
 
75
96
  renderer = get_visualization_renderer()
76
- if renderer:
77
- # Visualize in-place
78
- visual_model = await visualize_async(circuit_dataid)
79
- renderer(visual_model, link_label)
80
- return
81
-
82
97
  if display_url:
83
- print(link_label) # noqa: T201
84
-
85
- webbrowser.open_new_tab(app_url)
98
+ app_url = get_app_url(circuit_dataid, circuit)
99
+ print(f"Quantum program link: {app_url}") # noqa: T201
100
+ await renderer(circuit_dataid, circuit)
86
101
 
87
102
 
88
103
  async def _show_interactive(self: QuantumProgram, display_url: bool = True) -> None:
@@ -436,7 +436,7 @@ def _get_chemistry_quantum_main_params(
436
436
  name="t",
437
437
  classical_type=ClassicalArray(
438
438
  element_type=Real(),
439
- size=_get_hea_port_size(ansatz_parameters),
439
+ length=Expression(expr=str(_get_hea_port_size(ansatz_parameters))),
440
440
  ),
441
441
  ),
442
442
  ]
@@ -7,7 +7,6 @@ from classiq.interface.generator.constant import Constant
7
7
  from classiq.interface.generator.expressions.expression import Expression
8
8
  from classiq.interface.generator.functions.classical_type import (
9
9
  ClassicalArray,
10
- ClassicalList,
11
10
  Real,
12
11
  )
13
12
  from classiq.interface.generator.functions.port_declaration import (
@@ -76,7 +75,7 @@ def construct_combi_opt_py_model(
76
75
  constants=[
77
76
  Constant(
78
77
  name="hamiltonian",
79
- const_type=ClassicalList(element_type=Struct(name="PauliTerm")),
78
+ const_type=ClassicalArray(element_type=Struct(name="PauliTerm")),
80
79
  value=Expression(expr=f"[{pauli_qmod}]"),
81
80
  )
82
81
  ],
@@ -87,7 +86,8 @@ def construct_combi_opt_py_model(
87
86
  ClassicalParameterDeclaration(
88
87
  name="params_list",
89
88
  classical_type=ClassicalArray(
90
- element_type=Real(), size=qaoa_config.num_layers * 2
89
+ element_type=Real(),
90
+ length=Expression(expr=str(qaoa_config.num_layers * 2)),
91
91
  ),
92
92
  ),
93
93
  PortDeclaration(
@@ -3,5 +3,5 @@ from packaging.version import Version
3
3
  # This file was generated automatically
4
4
  # Please don't track in version control (DONTTRACK)
5
5
 
6
- SEMVER_VERSION = '0.79.1'
6
+ SEMVER_VERSION = '0.80.1'
7
7
  VERSION = str(Version(SEMVER_VERSION))
@@ -37,7 +37,7 @@ class DataID(pydantic.BaseModel):
37
37
 
38
38
 
39
39
  class QasmCode(pydantic.BaseModel):
40
- code: str = Field(..., max_length=MAX_FILE_LENGTH)
40
+ code: str = Field(..., max_length=MAX_FILE_LENGTH * 100)
41
41
 
42
42
 
43
43
  class AnalysisStatus(StrEnum):
@@ -1,12 +1,7 @@
1
- from collections.abc import Collection
1
+ from collections.abc import Collection, Iterable
2
2
  from functools import reduce
3
3
  from itertools import combinations
4
- from typing import (
5
- Any,
6
- Optional,
7
- Union,
8
- cast,
9
- )
4
+ from typing import Any, Optional, Union, cast
10
5
 
11
6
  import numpy as np
12
7
  import pydantic
@@ -283,7 +278,7 @@ def validate_operator_has_no_complex_coefficients(
283
278
  return pauli_operator
284
279
 
285
280
 
286
- def pauli_integers_to_str(paulis: list[Pauli]) -> str:
281
+ def pauli_integers_to_str(paulis: Iterable[Pauli]) -> str:
287
282
  return "".join([Pauli(pauli).name for pauli in paulis])
288
283
 
289
284
 
@@ -0,0 +1,18 @@
1
+ from typing import Union
2
+
3
+ from pydantic import BaseModel
4
+
5
+ from classiq.interface.generator.model.preferences.preferences import Preferences
6
+ from classiq.interface.generator.quantum_program import QuantumProgram
7
+
8
+ ExecutionParams = dict[str, Union[float, int, list[int], list[float]]]
9
+
10
+
11
+ class TranspilationParams(BaseModel):
12
+ quantum_program: QuantumProgram
13
+ preferences: Preferences
14
+
15
+
16
+ class ParameterAssignmentsParams(BaseModel):
17
+ quantum_program: QuantumProgram
18
+ parameters: ExecutionParams
@@ -4,7 +4,7 @@ from classiq.interface.generator.functions.classical_function_declaration import
4
4
  ClassicalFunctionDeclaration,
5
5
  )
6
6
  from classiq.interface.generator.functions.classical_type import (
7
- ClassicalList,
7
+ ClassicalArray,
8
8
  VQEResult,
9
9
  )
10
10
  from classiq.interface.generator.functions.type_name import Struct
@@ -35,7 +35,7 @@ MOLECULE_PROBLEM_TO_HAMILTONIAN = ClassicalFunctionDeclaration(
35
35
  name="problem", classical_type=Struct(name="MoleculeProblem")
36
36
  ),
37
37
  ],
38
- return_type=ClassicalList(element_type=Struct(name="PauliTerm")),
38
+ return_type=ClassicalArray(element_type=Struct(name="PauliTerm")),
39
39
  )
40
40
 
41
41
  FOCK_HAMILTONIAN_PROBLEM_TO_HAMILTONIAN = ClassicalFunctionDeclaration(
@@ -45,7 +45,7 @@ FOCK_HAMILTONIAN_PROBLEM_TO_HAMILTONIAN = ClassicalFunctionDeclaration(
45
45
  name="problem", classical_type=Struct(name="FockHamiltonianProblem")
46
46
  ),
47
47
  ],
48
- return_type=ClassicalList(element_type=Struct(name="PauliTerm")),
48
+ return_type=ClassicalArray(element_type=Struct(name="PauliTerm")),
49
49
  )
50
50
 
51
51
 
@@ -2,7 +2,7 @@ from classiq.interface.generator.functions.classical_function_declaration import
2
2
  ClassicalFunctionDeclaration,
3
3
  )
4
4
  from classiq.interface.generator.functions.classical_type import (
5
- ClassicalList,
5
+ ClassicalArray,
6
6
  Real,
7
7
  StructMetaType,
8
8
  VQEResult,
@@ -20,7 +20,7 @@ OPTIMIZATION_PROBLEM_TO_HAMILTONIAN = ClassicalFunctionDeclaration(
20
20
  ),
21
21
  ClassicalParameterDeclaration(name="penalty_energy", classical_type=Real()),
22
22
  ],
23
- return_type=ClassicalList(element_type=Struct(name="PauliTerm")),
23
+ return_type=ClassicalArray(element_type=Struct(name="PauliTerm")),
24
24
  )
25
25
 
26
26
  GET_OPTIMIZATION_SOLUTION = ClassicalFunctionDeclaration(
@@ -34,7 +34,7 @@ GET_OPTIMIZATION_SOLUTION = ClassicalFunctionDeclaration(
34
34
  ),
35
35
  ClassicalParameterDeclaration(name="penalty_energy", classical_type=Real()),
36
36
  ],
37
- return_type=ClassicalList(
37
+ return_type=ClassicalArray(
38
38
  element_type=Struct(name="CombinatorialOptimizationSolution")
39
39
  ),
40
40
  )
@@ -3,7 +3,7 @@ from classiq.interface.generator.functions.classical_function_declaration import
3
3
  )
4
4
  from classiq.interface.generator.functions.classical_type import (
5
5
  Bool,
6
- ClassicalList,
6
+ ClassicalArray,
7
7
  Integer,
8
8
  )
9
9
  from classiq.interface.model.classical_parameter_declaration import (
@@ -17,7 +17,7 @@ GRID_ENTANGLER_GRAPH = ClassicalFunctionDeclaration(
17
17
  ClassicalParameterDeclaration(name="schmidt_rank", classical_type=Integer()),
18
18
  ClassicalParameterDeclaration(name="grid_randomization", classical_type=Bool()),
19
19
  ],
20
- return_type=ClassicalList(element_type=ClassicalList(element_type=Integer())),
20
+ return_type=ClassicalArray(element_type=ClassicalArray(element_type=Integer())),
21
21
  )
22
22
 
23
23
  HYPERCUBE_ENTANGLER_GRAPH = ClassicalFunctionDeclaration(
@@ -25,5 +25,5 @@ HYPERCUBE_ENTANGLER_GRAPH = ClassicalFunctionDeclaration(
25
25
  positional_parameters=[
26
26
  ClassicalParameterDeclaration(name="num_qubits", classical_type=Integer()),
27
27
  ],
28
- return_type=ClassicalList(element_type=ClassicalList(element_type=Integer())),
28
+ return_type=ClassicalArray(element_type=ClassicalArray(element_type=Integer())),
29
29
  )
@@ -100,6 +100,14 @@ def bounds_to_integer_part_size(lb: float, ub: float) -> int:
100
100
  )
101
101
 
102
102
 
103
+ def bounds_to_attributes(
104
+ lb: float, ub: float, fraction_places: int, machine_precision: int
105
+ ) -> tuple[int, bool, int]:
106
+ fraction_places = min(fraction_places, machine_precision)
107
+ integers = bounds_to_integer_part_size(lb, ub)
108
+ return max(1, integers + fraction_places), lb < 0, fraction_places
109
+
110
+
103
111
  def limit_fraction_places(number: float, machine_precision: int) -> float:
104
112
  orig_bin_rep = binary_string(number)[::-1]
105
113
  orig_fractions = fraction_places(number)
@@ -1,4 +1,8 @@
1
1
  from classiq.interface.exceptions import ClassiqInternalExpansionError
2
+ from classiq.interface.generator.expressions.evaluated_expression import (
3
+ EvaluatedExpression,
4
+ )
5
+ from classiq.interface.generator.expressions.expression import Expression
2
6
  from classiq.interface.generator.expressions.proxies.classical.classical_array_proxy import (
3
7
  ClassicalArrayProxy,
4
8
  ClassicalTupleProxy,
@@ -14,7 +18,6 @@ from classiq.interface.generator.expressions.proxies.classical.classical_struct_
14
18
  )
15
19
  from classiq.interface.generator.functions.classical_type import (
16
20
  ClassicalArray,
17
- ClassicalList,
18
21
  ClassicalTuple,
19
22
  ClassicalType,
20
23
  )
@@ -26,8 +29,10 @@ def get_proxy_type(proxy: ClassicalProxy) -> ClassicalType:
26
29
  return proxy._classical_type
27
30
  if isinstance(proxy, ClassicalArrayProxy):
28
31
  if not isinstance(proxy.length, int):
29
- return ClassicalList(element_type=proxy._element_type)
30
- return ClassicalArray(element_type=proxy._element_type, size=proxy.length)
32
+ return ClassicalArray(element_type=proxy._element_type)
33
+ length = Expression(expr=str(proxy.length))
34
+ length._evaluated_expr = EvaluatedExpression(value=proxy.length)
35
+ return ClassicalArray(element_type=proxy._element_type, length=length)
31
36
  if isinstance(proxy, ClassicalTupleProxy):
32
37
  return ClassicalTuple(element_types=proxy._element_types)
33
38
  if isinstance(proxy, ClassicalStructProxy):