classiq 0.94.2__py3-none-any.whl → 0.96.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of classiq might be problematic. Click here for more details.

Files changed (76) hide show
  1. classiq/_internals/api_wrapper.py +0 -83
  2. classiq/_internals/authentication/auth0.py +32 -3
  3. classiq/_internals/authentication/authorization_code.py +9 -0
  4. classiq/_internals/authentication/authorization_flow.py +41 -0
  5. classiq/_internals/authentication/device.py +31 -50
  6. classiq/_internals/authentication/hybrid_flow.py +19 -0
  7. classiq/_internals/authentication/token_manager.py +5 -4
  8. classiq/applications/__init__.py +2 -2
  9. classiq/applications/iqae/iqae.py +6 -3
  10. classiq/applications/qnn/gradients/simple_quantum_gradient.py +1 -1
  11. classiq/applications/qnn/qlayer.py +1 -1
  12. classiq/applications/qnn/torch_utils.py +2 -2
  13. classiq/applications/qsp/qsp.py +6 -5
  14. classiq/evaluators/qmod_node_evaluators/classical_function_evaluation.py +10 -0
  15. classiq/execution/__init__.py +0 -3
  16. classiq/execution/user_budgets.py +0 -1
  17. classiq/interface/_version.py +1 -1
  18. classiq/interface/backend/backend_preferences.py +11 -35
  19. classiq/interface/backend/quantum_backend_providers.py +0 -2
  20. classiq/interface/exceptions.py +0 -4
  21. classiq/interface/generator/application_apis/__init__.py +0 -1
  22. classiq/interface/generator/arith/register_user_input.py +1 -1
  23. classiq/interface/generator/function_param_list.py +0 -2
  24. classiq/interface/generator/generated_circuit_data.py +1 -6
  25. classiq/interface/generator/hardware_efficient_ansatz.py +1 -1
  26. classiq/interface/generator/quantum_function_call.py +1 -1
  27. classiq/interface/generator/quantum_program.py +0 -4
  28. classiq/interface/generator/transpiler_basis_gates.py +3 -0
  29. classiq/interface/generator/types/builtin_enum_declarations.py +0 -9
  30. classiq/interface/hardware.py +0 -1
  31. classiq/interface/interface_version.py +1 -1
  32. classiq/interface/model/block.py +4 -0
  33. classiq/interface/model/classical_if.py +4 -0
  34. classiq/interface/model/control.py +7 -0
  35. classiq/interface/model/invert.py +4 -0
  36. classiq/interface/model/model_visitor.py +40 -1
  37. classiq/interface/model/power.py +4 -0
  38. classiq/interface/model/quantum_statement.py +8 -1
  39. classiq/interface/model/repeat.py +4 -0
  40. classiq/interface/model/skip_control.py +4 -0
  41. classiq/interface/model/within_apply_operation.py +4 -0
  42. classiq/interface/server/routes.py +0 -12
  43. classiq/model_expansions/generative_functions.py +6 -8
  44. classiq/model_expansions/interpreters/base_interpreter.py +1 -1
  45. classiq/model_expansions/interpreters/frontend_generative_interpreter.py +2 -1
  46. classiq/model_expansions/visitors/symbolic_param_inference.py +3 -3
  47. classiq/model_expansions/visitors/uncomputation_signature_inference.py +14 -3
  48. classiq/open_library/functions/__init__.py +3 -2
  49. classiq/open_library/functions/amplitude_loading.py +85 -0
  50. classiq/open_library/functions/lcu.py +47 -18
  51. classiq/open_library/functions/modular_exponentiation.py +5 -8
  52. classiq/open_library/functions/qsvt.py +4 -4
  53. classiq/open_library/functions/state_preparation.py +7 -7
  54. classiq/qmod/builtins/classical_execution_primitives.py +0 -12
  55. classiq/qmod/builtins/enums.py +15 -17
  56. classiq/qmod/builtins/functions/__init__.py +5 -5
  57. classiq/qmod/builtins/functions/allocation.py +21 -0
  58. classiq/qmod/builtins/functions/mcx.py +7 -0
  59. classiq/qmod/builtins/operations.py +125 -23
  60. classiq/qmod/builtins/structs.py +22 -33
  61. classiq/qmod/semantics/annotation/call_annotation.py +3 -3
  62. classiq/qmod/semantics/error_manager.py +7 -8
  63. classiq/qmod/utilities.py +0 -10
  64. {classiq-0.94.2.dist-info → classiq-0.96.0.dist-info}/METADATA +1 -1
  65. {classiq-0.94.2.dist-info → classiq-0.96.0.dist-info}/RECORD +67 -71
  66. {classiq-0.94.2.dist-info → classiq-0.96.0.dist-info}/WHEEL +1 -1
  67. classiq/applications/qsvm/__init__.py +0 -8
  68. classiq/applications/qsvm/qsvm.py +0 -11
  69. classiq/execution/iqcc.py +0 -128
  70. classiq/interface/applications/qsvm.py +0 -114
  71. classiq/interface/execution/iqcc.py +0 -42
  72. classiq/interface/generator/application_apis/qsvm_declarations.py +0 -6
  73. classiq/interface/generator/qsvm.py +0 -96
  74. classiq/open_library/functions/lookup_table.py +0 -58
  75. classiq/qmod/builtins/functions/qsvm.py +0 -24
  76. {classiq-0.94.2.dist-info → classiq-0.96.0.dist-info}/licenses/LICENSE.txt +0 -0
@@ -12,15 +12,6 @@ from classiq.interface.analyzer.analysis_params import AnalysisRBParams
12
12
  from classiq.interface.analyzer.result import GraphStatus, QmodCode
13
13
  from classiq.interface.enum_utils import StrEnum
14
14
  from classiq.interface.exceptions import ClassiqAPIError, ClassiqValueError
15
- from classiq.interface.execution.iqcc import (
16
- IQCCAuthItemsDetails,
17
- IQCCInitAuthData,
18
- IQCCInitAuthResponse,
19
- IQCCListAuthMethods,
20
- IQCCListAuthTargets,
21
- IQCCProbeAuthData,
22
- IQCCProbeAuthResponse,
23
- )
24
15
  from classiq.interface.execution.primitives import PrimitivesInput
25
16
  from classiq.interface.executor import execution_request
26
17
  from classiq.interface.executor.quantum_program_params import (
@@ -488,80 +479,6 @@ class ApiWrapper:
488
479
  raise ClassiqAPIError(f"Unexpected value: {data}")
489
480
  return [HardwareInformation.model_validate(info) for info in data]
490
481
 
491
- @classmethod
492
- async def call_iqcc_init_auth(
493
- cls,
494
- data: IQCCInitAuthData,
495
- http_client: httpx.AsyncClient | None = None,
496
- ) -> IQCCInitAuthResponse:
497
- response = await cls._call_task_pydantic(
498
- http_method=HTTPMethod.PUT,
499
- url=f"{routes.IQCC_INIT_AUTH_FULL_PATH}",
500
- model=data,
501
- http_client=http_client,
502
- )
503
- return IQCCInitAuthResponse.model_validate(response)
504
-
505
- @classmethod
506
- async def call_iqcc_probe_auth(
507
- cls,
508
- data: IQCCProbeAuthData,
509
- http_client: httpx.AsyncClient | None = None,
510
- ) -> IQCCProbeAuthResponse | None:
511
- try:
512
- response = await cls._call_task_pydantic(
513
- http_method=HTTPMethod.PUT,
514
- url=f"{routes.IQCC_PROBE_AUTH_FULL_PATH}",
515
- model=data,
516
- http_client=http_client,
517
- )
518
- except ClassiqAPIError as ex:
519
- if ex.status_code == 418:
520
- return None
521
- raise
522
-
523
- return IQCCProbeAuthResponse.model_validate(response)
524
-
525
- @classmethod
526
- async def call_iqcc_list_auth_scopes(
527
- cls,
528
- http_client: httpx.AsyncClient | None = None,
529
- ) -> IQCCAuthItemsDetails:
530
- response = await cls._call_task(
531
- http_method=HTTPMethod.GET,
532
- url=routes.IQCC_LIST_AUTH_SCOPES_FULL_PATH,
533
- http_client=http_client,
534
- )
535
- return IQCCAuthItemsDetails.model_validate(response)
536
-
537
- @classmethod
538
- async def call_iqcc_list_auth_methods(
539
- cls,
540
- data: IQCCListAuthMethods,
541
- http_client: httpx.AsyncClient | None = None,
542
- ) -> IQCCAuthItemsDetails:
543
- response = await cls._call_task_pydantic(
544
- http_method=HTTPMethod.PUT,
545
- url=routes.IQCC_LIST_AUTH_METHODS_FULL_PATH,
546
- model=data,
547
- http_client=http_client,
548
- )
549
- return IQCCAuthItemsDetails.model_validate(response)
550
-
551
- @classmethod
552
- async def call_iqcc_list_auth_targets(
553
- cls,
554
- data: IQCCListAuthTargets,
555
- http_client: httpx.AsyncClient | None = None,
556
- ) -> IQCCAuthItemsDetails:
557
- response = await cls._call_task_pydantic(
558
- http_method=HTTPMethod.PUT,
559
- url=routes.IQCC_LIST_AUTH_TARGETS_FULL_PATH,
560
- model=data,
561
- http_client=http_client,
562
- )
563
- return IQCCAuthItemsDetails.model_validate(response)
564
-
565
482
  @classmethod
566
483
  async def call_get_all_budgets(cls) -> list[UserBudget]:
567
484
  data = await client().call_api(
@@ -1,4 +1,5 @@
1
1
  import urllib.parse
2
+ import warnings
2
3
  from dataclasses import dataclass
3
4
  from typing import Any
4
5
 
@@ -20,6 +21,7 @@ class AuthSettings(BaseSettings):
20
21
  default="f6721qMOVoDAOVkzrv8YaWassRKSFX6Y",
21
22
  validation_alias="CLASSIQ_AUTH_CLIENT_ID",
22
23
  )
24
+ organization: str = Field(default="", validation_alias="CLASSIQ_AUTH_ORGANIZATION")
23
25
 
24
26
  model_config = SettingsConfigDict(extra="allow")
25
27
 
@@ -53,6 +55,10 @@ class Auth0:
53
55
  def _client_id(self) -> str:
54
56
  return self._auth_settings.client_id
55
57
 
58
+ @property
59
+ def _organization(self) -> str:
60
+ return self._auth_settings.organization
61
+
56
62
  async def _make_request(
57
63
  self,
58
64
  url: str,
@@ -76,13 +82,20 @@ class Auth0:
76
82
  f"Request to Auth0 failed with error code {code}: {data.get('error')}"
77
83
  )
78
84
 
79
- async def get_device_data(self, get_refresh_token: bool = True) -> dict[str, Any]:
85
+ async def get_device_data(
86
+ self, require_refresh_token: bool = True
87
+ ) -> dict[str, Any]:
80
88
  payload = {
81
- "client_id": self._auth_settings.client_id,
89
+ "client_id": self._client_id,
82
90
  "audience": self._auth_settings.audience,
83
91
  }
84
- if get_refresh_token:
92
+ if require_refresh_token:
85
93
  payload["scope"] = "offline_access"
94
+ if self._organization:
95
+ warnings.warn(
96
+ "Organizations are not supported in device auth flow.",
97
+ stacklevel=1,
98
+ )
86
99
 
87
100
  return await self._make_request(
88
101
  url="/oauth/device/code",
@@ -102,6 +115,22 @@ class Auth0:
102
115
  allow_error=codes.FORBIDDEN,
103
116
  )
104
117
 
118
+ def get_authorize_url(
119
+ self, redirect_uri: str, require_refresh_token: bool = True
120
+ ) -> str:
121
+ params = {
122
+ "client_id": self._client_id,
123
+ "response_type": "code",
124
+ "audience": self._auth_settings.audience,
125
+ "redirect_uri": redirect_uri,
126
+ }
127
+ if require_refresh_token:
128
+ params["scope"] = "offline_access"
129
+ if self._organization:
130
+ # Otherwise, let the Auth0 handle
131
+ params["organization"] = self._organization
132
+ return f"{self._base_url}/authorize?{urllib.parse.urlencode(params)}"
133
+
105
134
  async def refresh_access_token(self, refresh_token: str) -> Tokens:
106
135
  # TODO handle failure
107
136
  payload = {
@@ -0,0 +1,9 @@
1
+ from classiq._internals.authentication.authorization_flow import AuthorizationFlow
2
+
3
+
4
+ class AuthorizationCodeFlow(AuthorizationFlow):
5
+ async def authorize(self, redirect_uri: str) -> None:
6
+ auth_url = self.auth0_client.get_authorize_url(
7
+ redirect_uri, self.require_refresh_token
8
+ )
9
+ self.open_url(auth_url)
@@ -0,0 +1,41 @@
1
+ import webbrowser
2
+ from typing import Any
3
+
4
+ from classiq.interface.exceptions import ClassiqAuthenticationError
5
+
6
+ from classiq._internals.authentication.auth0 import Auth0, Tokens
7
+
8
+
9
+ class AuthorizationFlow:
10
+ def __init__(self, require_refresh_token: bool = True, text_only: bool = False):
11
+ self.require_refresh_token = require_refresh_token
12
+ self.text_only = text_only
13
+ self.auth0_client = Auth0()
14
+
15
+ async def get_tokens(self) -> Tokens:
16
+ raise NotImplementedError
17
+
18
+ def handle_ready_data(self, data: dict[str, Any]) -> Tokens:
19
+ access_token: str | None = data.get("access_token") or None
20
+ # If refresh token was not requested, this would be None
21
+ refresh_token: str | None = data.get("refresh_token") or None
22
+
23
+ if access_token is None or (
24
+ self.require_refresh_token is True and refresh_token is None
25
+ ):
26
+ raise ClassiqAuthenticationError(
27
+ "Token generation failed for unknown reason (missing access token or refresh token)."
28
+ )
29
+
30
+ return Tokens(access_token=access_token, refresh_token=refresh_token)
31
+
32
+ def open_url(self, url: str) -> None:
33
+ if self.text_only:
34
+ print( # noqa: T201
35
+ f"Please visit this URL from any trusted device to authenticate: {url}"
36
+ )
37
+ else:
38
+ webbrowser.open(url)
39
+ print( # noqa: T201
40
+ f"If a browser doesn't automatically open, please visit this URL from any trusted device to authenticate: {url}"
41
+ )
@@ -1,6 +1,6 @@
1
1
  import asyncio
2
- import webbrowser
3
2
  from collections.abc import Iterable
3
+ from dataclasses import dataclass
4
4
  from datetime import timedelta
5
5
  from typing import Any, TypeVar
6
6
 
@@ -10,74 +10,55 @@ from classiq.interface.exceptions import (
10
10
  )
11
11
 
12
12
  from classiq._internals.async_utils import poll_for
13
- from classiq._internals.authentication.auth0 import Auth0, Tokens
13
+ from classiq._internals.authentication.auth0 import Tokens
14
+ from classiq._internals.authentication.authorization_flow import AuthorizationFlow
14
15
 
15
16
  T = TypeVar("T")
16
17
 
17
18
 
18
- class DeviceRegistrar:
19
+ @dataclass
20
+ class DeviceData:
21
+ user_code: str
22
+ device_code: str
23
+ interval: float
24
+ expires_in: float
25
+ verification_uri: str
26
+ verification_uri_complete: str
27
+
28
+
29
+ class DeviceCodeFlow(AuthorizationFlow):
19
30
  _TIMEOUT_ERROR = (
20
31
  "Device registration timed out. Please re-initiate the flow and "
21
32
  "authorize the device within the timeout."
22
33
  )
23
34
  _TIMEOUT_SEC: float = timedelta(minutes=15).total_seconds()
24
35
 
25
- @classmethod
26
- async def register(
27
- cls, get_refresh_token: bool = True, text_only: bool = False
28
- ) -> Tokens:
29
- auth0_client = Auth0()
30
- data: dict[str, Any] = await auth0_client.get_device_data(
31
- get_refresh_token=get_refresh_token
36
+ async def get_device_data(self) -> DeviceData:
37
+ device_data: dict[str, Any] = await self.auth0_client.get_device_data(
38
+ require_refresh_token=self.require_refresh_token
32
39
  )
40
+ return DeviceData(**device_data)
33
41
 
34
- print(f"Your user code: {data['user_code']}") # noqa: T201
35
- verification_url = data["verification_uri_complete"]
36
- print( # noqa: T201
37
- f"If a browser doesn't automatically open, please visit this URL from any trusted device: {verification_url}"
38
- )
39
- if not text_only:
40
- webbrowser.open(verification_url)
41
- timeout = min(data["expires_in"], cls._TIMEOUT_SEC)
42
- return await cls._poll_tokens(
43
- auth0_client=auth0_client,
44
- device_code=data["device_code"],
45
- interval=data["interval"],
42
+ async def poll_tokens(self, device_data: DeviceData) -> Tokens:
43
+ interval = device_data.interval
44
+ timeout = min(device_data.expires_in, self._TIMEOUT_SEC)
45
+ return await self._poll_tokens(
46
+ device_code=device_data.device_code,
47
+ interval=interval,
46
48
  timeout=timeout,
47
- get_refresh_token=get_refresh_token,
48
49
  )
49
50
 
50
- @classmethod
51
- def _handle_ready_data(
52
- cls, data: dict[str, Any], get_refresh_token: bool
53
- ) -> Tokens:
54
- access_token: str | None = data.get("access_token")
55
- # If refresh token was not requested, this would be None
56
- refresh_token: str | None = data.get("refresh_token")
57
-
58
- if access_token is None or (
59
- get_refresh_token is True and refresh_token is None
60
- ):
61
- raise ClassiqAuthenticationError(
62
- "Token generation failed for unknown reason."
63
- )
64
-
65
- return Tokens(access_token=access_token, refresh_token=refresh_token)
66
-
67
- @classmethod
68
51
  async def _poll_tokens(
69
- cls,
70
- auth0_client: Auth0,
52
+ self,
71
53
  device_code: str,
72
- interval: int,
54
+ interval: float,
73
55
  timeout: float,
74
- get_refresh_token: bool = True,
75
56
  ) -> Tokens:
76
57
  async def poller() -> dict[str, Any]:
77
58
  nonlocal device_code
78
- return await auth0_client.poll_tokens(device_code=device_code)
59
+ return await self.auth0_client.poll_tokens(device_code=device_code)
79
60
 
80
- def interval_coro() -> Iterable[int]:
61
+ def interval_coro() -> Iterable[float]:
81
62
  nonlocal interval
82
63
  while True:
83
64
  yield interval
@@ -88,14 +69,14 @@ class DeviceRegistrar:
88
69
  ):
89
70
  error_code: str | None = data.get("error")
90
71
  if error_code is None:
91
- return cls._handle_ready_data(data, get_refresh_token)
72
+ return self.handle_ready_data(data)
92
73
  elif error_code == "authorization_pending":
93
74
  pass
94
75
  elif error_code == "slow_down":
95
76
  # This value is used by poll_for via interval_coro
96
77
  interval *= 2
97
78
  elif error_code == "expired_token":
98
- raise ClassiqExpiredTokenError(cls._TIMEOUT_ERROR)
79
+ raise ClassiqExpiredTokenError(self._TIMEOUT_ERROR)
99
80
  elif error_code == "access_denied":
100
81
  error_description = data.get("error_description")
101
82
  if error_description is None:
@@ -109,4 +90,4 @@ class DeviceRegistrar:
109
90
  f"Device registration failed with an unknown error: {error_code}."
110
91
  )
111
92
  else:
112
- raise ClassiqAuthenticationError(cls._TIMEOUT_ERROR)
93
+ raise ClassiqAuthenticationError(self._TIMEOUT_ERROR)
@@ -0,0 +1,19 @@
1
+ from classiq._internals.authentication.auth0 import Tokens
2
+ from classiq._internals.authentication.authorization_code import AuthorizationCodeFlow
3
+ from classiq._internals.authentication.authorization_flow import AuthorizationFlow
4
+ from classiq._internals.authentication.device import DeviceCodeFlow
5
+
6
+
7
+ class HybridFlow(AuthorizationFlow):
8
+ def __init__(
9
+ self, require_refresh_token: bool = True, text_only: bool = False
10
+ ) -> None:
11
+ super().__init__(require_refresh_token, text_only)
12
+ self.device_flow = DeviceCodeFlow(require_refresh_token, text_only)
13
+ self.auth_code_flow = AuthorizationCodeFlow(require_refresh_token, text_only)
14
+
15
+ async def get_tokens(self) -> Tokens:
16
+ device_data = await self.device_flow.get_device_data()
17
+ await self.auth_code_flow.authorize(device_data.verification_uri_complete)
18
+ print(f"Your user code: {device_data.user_code}") # noqa: T201
19
+ return await self.device_flow.poll_tokens(device_data)
@@ -10,8 +10,8 @@ from classiq.interface.exceptions import (
10
10
  )
11
11
 
12
12
  from classiq._internals.authentication import password_manager as pm
13
- from classiq._internals.authentication.auth0 import Auth0
14
- from classiq._internals.authentication.device import DeviceRegistrar, Tokens
13
+ from classiq._internals.authentication.auth0 import Auth0, Tokens
14
+ from classiq._internals.authentication.hybrid_flow import HybridFlow
15
15
  from classiq._internals.config import Configuration
16
16
 
17
17
  PASSWORD_MANAGERS: Sequence[type[pm.PasswordManager]] = [
@@ -126,7 +126,8 @@ class TokenManager:
126
126
  async def _authentication_helper(self) -> None:
127
127
  # TODO: consider using refresh token rotation
128
128
  # (https://auth0.com/docs/tokens/refresh-tokens/refresh-token-rotation)
129
- tokens = await DeviceRegistrar.register(
130
- get_refresh_token=True, text_only=self._config.text_only
129
+ authorization_flow = HybridFlow(
130
+ require_refresh_token=True, text_only=self._config.text_only
131
131
  )
132
+ tokens = await authorization_flow.get_tokens()
132
133
  self._save_tokens(tokens, force_override_refresh_token=True)
@@ -1,6 +1,6 @@
1
- from classiq.applications import chemistry, combinatorial_optimization, qsp, qsvm
1
+ from classiq.applications import chemistry, combinatorial_optimization, qsp
2
2
 
3
- __all__ = ["chemistry", "combinatorial_optimization", "qsp", "qsvm"]
3
+ __all__ = ["chemistry", "combinatorial_optimization", "qsp"]
4
4
 
5
5
 
6
6
  _NON_IMPORTED_PUBLIC_SUBMODULES = ["qnn"]
@@ -20,8 +20,10 @@ from classiq.qmod import (
20
20
  QCallable,
21
21
  )
22
22
  from classiq.qmod.builtins import Z, allocate, bind, within_apply
23
+ from classiq.qmod.builtins.functions.allocation import drop
23
24
  from classiq.qmod.create_model_function import create_model
24
- from classiq.qmod.qfunc import qfunc
25
+ from classiq.qmod.qfunc import qfunc, qperm
26
+ from classiq.qmod.qmod_variable import Const
25
27
  from classiq.synthesis import synthesize
26
28
 
27
29
 
@@ -83,8 +85,8 @@ class IQAE:
83
85
  def space_transform(est_reg: QArray) -> None:
84
86
  state_prep_op(est_reg[0 : est_reg.len - 1], est_reg[est_reg.len - 1])
85
87
 
86
- @qfunc
87
- def oracle(est_reg: QArray) -> None:
88
+ @qperm
89
+ def oracle(est_reg: Const[QArray]) -> None:
88
90
  Z(est_reg[est_reg.len - 1])
89
91
 
90
92
  @qfunc
@@ -105,6 +107,7 @@ class IQAE:
105
107
  est_reg,
106
108
  ),
107
109
  )
110
+ drop(problem_vars)
108
111
 
109
112
  if self._model is None:
110
113
  self._model = create_model(
@@ -59,7 +59,7 @@ def _differentiate_tensor(
59
59
  # The minus comes from the way pytorch defines diff
60
60
  # it diffs the second object minus the first
61
61
  # where we want the first minus the second
62
- diff = -tensor.diff(axis=axis).squeeze(axis) # type: ignore[call-arg] # torch does accept `axis` keyword
62
+ diff = -tensor.diff(axis=axis).squeeze(axis)
63
63
  return diff / (2 * epsilon)
64
64
 
65
65
 
@@ -104,7 +104,7 @@ class QLayerFunction(torch.autograd.Function):
104
104
  )
105
105
 
106
106
  @staticmethod
107
- def backward( # type: ignore[override]
107
+ def backward(
108
108
  ctx: Any, grad_output: Tensor
109
109
  ) -> tuple[Tensor | None, Tensor | None, None, None, None, None]:
110
110
  """
@@ -23,7 +23,7 @@ def get_shape_second_dimension(shape: torch.Size) -> int:
23
23
  if len(shape) == 1:
24
24
  return 1
25
25
  elif len(shape) == 2:
26
- return shape[1]
26
+ return shape[1] # type: ignore[index]
27
27
  else:
28
28
  raise ClassiqValueError("Invalid shape dimension - must be 1D or 2D")
29
29
 
@@ -33,7 +33,7 @@ def get_shape_first_dimension(shape: torch.Size) -> int:
33
33
  raise ClassiqValueError("Invalid shape type - must have `__len__`")
34
34
 
35
35
  if len(shape) in (1, 2):
36
- return shape[0]
36
+ return shape[0] # type: ignore[index]
37
37
  else:
38
38
  raise ClassiqValueError("Invalid shape dimension - must be 1D or 2D")
39
39
 
@@ -50,7 +50,7 @@ def qsvt_phases(
50
50
  ) -> np.ndarray:
51
51
  r"""
52
52
  Get QSVT phases that will generate the given Chebyshev polynomial.
53
- The phases are ready to be used in `qsvt` and `qsvt_lcu` functions in the classiq library. The convetion
53
+ The phases are ready to be used in `qsvt` and `qsvt_lcu` functions in the classiq library. The convention
54
54
  is the reflection signal operator, and the measurement basis is the hadamard basis (see https://arxiv.org/abs/2105.02859
55
55
  APPENDIX A.).
56
56
  The current implementation is using the pyqsp package, based on techniques in https://arxiv.org/abs/2003.02831.
@@ -118,7 +118,7 @@ def qsvt_phases(
118
118
 
119
119
  def _plot_qsp_approx(
120
120
  poly_cheb: np.ndarray,
121
- f_target: Callable[[np.ndarray], np.ndarray],
121
+ f_target: Callable[[float], complex],
122
122
  interval: tuple[float, float] = (-1, 1),
123
123
  ) -> None:
124
124
  from matplotlib import pyplot as plt
@@ -126,7 +126,7 @@ def _plot_qsp_approx(
126
126
  grid_full = np.linspace(-1, 1, 3000)
127
127
  grid_interval = np.linspace(interval[0], interval[1], 3000)
128
128
 
129
- y_target = f_target(grid_interval)
129
+ y_target = np.vectorize(f_target, otypes=[float])(grid_interval)
130
130
  y_approx = np.polynomial.Chebyshev(poly_cheb)(grid_full)
131
131
 
132
132
  # Plot
@@ -153,7 +153,7 @@ def _plot_qsp_approx(
153
153
 
154
154
 
155
155
  def qsp_approximate(
156
- f_target: Callable[[np.ndarray], np.ndarray],
156
+ f_target: Callable[[float], complex],
157
157
  degree: int,
158
158
  parity: int | None = None,
159
159
  interval: tuple[float, float] = (-1, 1),
@@ -193,7 +193,8 @@ def qsp_approximate(
193
193
  # Select grid points for the objective in [w_min, w_max]
194
194
  xj_obj = xj_full[(xj_full >= interval[0]) & (xj_full <= interval[1])]
195
195
 
196
- yj_obj = f_target(xj_obj)
196
+ yj_obj = np.vectorize(f_target, otypes=[float])(xj_obj)
197
+
197
198
  # heuristic verification
198
199
  bound = min(1, bound)
199
200
  assert (
@@ -7,6 +7,7 @@ import sympy
7
7
  from classiq.interface.exceptions import (
8
8
  ClassiqExpansionError,
9
9
  ClassiqInternalExpansionError,
10
+ ClassiqValueError,
10
11
  )
11
12
  from classiq.interface.generator.functions.classical_function_declaration import (
12
13
  ClassicalFunctionDeclaration,
@@ -208,6 +209,15 @@ def try_eval_sympy_function(
208
209
 
209
210
  def try_eval_builtin_function(
210
211
  expr_val: QmodAnnotatedExpression, node: ast.Call, func_name: str
212
+ ) -> bool:
213
+ try:
214
+ return _try_eval_builtin_function(expr_val, node, func_name)
215
+ except ValueError as e:
216
+ raise ClassiqValueError(str(e)) from e
217
+
218
+
219
+ def _try_eval_builtin_function(
220
+ expr_val: QmodAnnotatedExpression, node: ast.Call, func_name: str
211
221
  ) -> bool:
212
222
  args_are_int = all(isinstance(expr_val.get_type(arg), Integer) for arg in node.args)
213
223
  args_are_real = all(
@@ -8,7 +8,6 @@ from ..interface.executor.execution_preferences import __all__ as _ep_all
8
8
  from ..interface.executor.result import ExecutionDetails
9
9
  from ..interface.executor.vqe_result import VQESolverResult
10
10
  from .execution_session import ExecutionSession
11
- from .iqcc import generate_iqcc_token, generate_iqcc_token_async
12
11
  from .jobs import ExecutionJob, get_execution_jobs, get_execution_jobs_async
13
12
  from .qnn import execute_qnn
14
13
  from .user_budgets import (
@@ -33,8 +32,6 @@ __all__ = (
33
32
  "get_execution_jobs_async",
34
33
  "ExecutionSession",
35
34
  "execute_qnn",
36
- "generate_iqcc_token",
37
- "generate_iqcc_token_async",
38
35
  "get_budget",
39
36
  "get_budget_async",
40
37
  "set_budget_limit",
@@ -14,7 +14,6 @@ PROVIDER_MAPPER = {
14
14
  ProviderVendor.OQC: "OQC",
15
15
  ProviderVendor.INTEL: "INTEL",
16
16
  ProviderVendor.AQT: "AQT",
17
- ProviderVendor.IQCC: "IQCC",
18
17
  ProviderVendor.CLASSIQ: "CLASSIQ",
19
18
  }
20
19
 
@@ -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.94.2'
6
+ SEMVER_VERSION = '0.96.0'
7
7
  VERSION = str(Version(SEMVER_VERSION))
@@ -172,10 +172,11 @@ class AwsBackendPreferences(BackendPreferences):
172
172
  backend_service_provider (ProviderTypeVendor.AMAZON_BRAKET):
173
173
  The service provider for the backend, which is Amazon Braket.
174
174
 
175
- aws_role_arn (pydantic_backend.PydanticAwsRoleArn):
176
- The Amazon Resource Name (ARN) of the role that will be assumed for execution
177
- on your Braket account. This is a required field and should be provided to allow
178
- secure and authorized access to AWS resources.
175
+ aws_access_key_id (str):
176
+ The access key id of AWS user with full braket access
177
+
178
+ aws_secret_access_key (str):
179
+ The secret key assigned to the access key id for the user with full braket access.
179
180
 
180
181
  s3_bucket_name (str):
181
182
  The name of the S3 bucket where results and other related data will be stored.
@@ -193,9 +194,13 @@ class AwsBackendPreferences(BackendPreferences):
193
194
  backend_service_provider: ProviderTypeVendor.AMAZON_BRAKET = pydantic.Field(
194
195
  default=ProviderVendor.AMAZON_BRAKET
195
196
  )
196
- aws_role_arn: str | None = pydantic.Field(
197
+ aws_access_key_id: str | None = pydantic.Field(
198
+ default=None,
199
+ description="Key id assigned to user with credentials to access Braket service",
200
+ )
201
+ aws_secret_access_key: str | None = pydantic.Field(
197
202
  default=None,
198
- description="ARN of the role to be assumed for execution on your Braket account.",
203
+ description="Secret access key assigned to user with credentials to access Braket service",
199
204
  )
200
205
  s3_bucket_name: str | None = pydantic.Field(
201
206
  default=None, description="S3 Bucket Name"
@@ -428,33 +433,6 @@ class AQTBackendPreferences(BackendPreferences):
428
433
  workspace: str = pydantic.Field(description="AQT workspace")
429
434
 
430
435
 
431
- class IQCCBackendPreferences(BackendPreferences):
432
- """
433
- NOTE: This is a work in progress and is subject to change.
434
-
435
- Represents the backend preferences specific to IQCC (Israeli Quantum Computing
436
- Center).
437
-
438
- Attributes:
439
- auth_token: The authorization token generated by calling `generate_iqcc_token`.
440
- target_id: The target ID of the login node.
441
- target_scope_id: The scope ID of the specified target.
442
- ssh_user_name: The user name to use when connecting to the SSH server on the login node.
443
- ssh_key: The private key to use when connecting to the SSH server on the login node.
444
- slurm_account: The account to use when initiating SLURM jobs.
445
- """
446
-
447
- backend_service_provider: ProviderTypeVendor.IQCC = pydantic.Field(
448
- default=ProviderVendor.IQCC
449
- )
450
- auth_token: str
451
- target_id: str
452
- target_scope_id: str
453
- ssh_user_name: str
454
- ssh_key: str
455
- slurm_account: str
456
-
457
-
458
436
  class CINECABackendPreferences(BackendPreferences):
459
437
  """
460
438
  Represents the backend preferences specific to CINECA.
@@ -507,7 +485,6 @@ BackendPreferencesTypes = Union[
507
485
  OQCBackendPreferences,
508
486
  IntelBackendPreferences,
509
487
  AQTBackendPreferences,
510
- IQCCBackendPreferences,
511
488
  CINECABackendPreferences,
512
489
  ]
513
490
 
@@ -525,7 +502,6 @@ __all__ = [
525
502
  "ClassiqSimulatorBackendNames",
526
503
  "GCPBackendPreferences",
527
504
  "IBMBackendPreferences",
528
- "IQCCBackendPreferences",
529
505
  "IntelBackendNames",
530
506
  "IntelBackendPreferences",
531
507
  "IonqBackendNames",