classiq 0.104.0__py3-none-any.whl → 1.0.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.
Files changed (52) hide show
  1. classiq/__init__.py +2 -0
  2. classiq/_internals/authentication/auth0.py +29 -0
  3. classiq/_internals/authentication/auth_flow_factory.py +43 -0
  4. classiq/_internals/authentication/machine_credentials_flow.py +26 -0
  5. classiq/_internals/authentication/password_manager.py +84 -0
  6. classiq/_internals/authentication/token_manager.py +24 -8
  7. classiq/analyzer/show_interactive_hack.py +0 -8
  8. classiq/applications/combinatorial_optimization/combinatorial_problem.py +1 -1
  9. classiq/execution/all_hardware_devices.py +59 -1
  10. classiq/execution/functions/__init__.py +11 -1
  11. classiq/execution/functions/expectation_value.py +106 -0
  12. classiq/execution/functions/minimize.py +90 -0
  13. classiq/execution/functions/sample.py +8 -189
  14. classiq/execution/functions/state_vector.py +113 -0
  15. classiq/execution/functions/util/__init__.py +0 -0
  16. classiq/execution/functions/util/backend_preferences.py +188 -0
  17. classiq/interface/_version.py +1 -1
  18. classiq/interface/backend/backend_preferences.py +66 -0
  19. classiq/interface/backend/quantum_backend_providers.py +11 -0
  20. classiq/interface/exceptions.py +0 -4
  21. classiq/interface/generator/arith/binary_ops.py +24 -0
  22. classiq/interface/generator/arith/number_utils.py +15 -6
  23. classiq/interface/generator/compiler_keywords.py +1 -0
  24. classiq/interface/generator/function_param_list.py +4 -0
  25. classiq/interface/generator/function_params.py +1 -1
  26. classiq/interface/generator/functions/classical_type.py +15 -0
  27. classiq/interface/generator/functions/type_name.py +17 -4
  28. classiq/interface/generator/transpiler_basis_gates.py +1 -0
  29. classiq/interface/generator/types/compilation_metadata.py +15 -6
  30. classiq/interface/hardware.py +1 -0
  31. classiq/interface/interface_version.py +1 -1
  32. classiq/interface/model/model.py +19 -0
  33. classiq/interface/model/quantum_type.py +15 -0
  34. classiq/interface/qubits_mapping/__init__.py +4 -0
  35. classiq/interface/qubits_mapping/path_expr_range.py +69 -0
  36. classiq/interface/qubits_mapping/qubits_mapping.py +231 -0
  37. classiq/interface/qubits_mapping/slices.py +112 -0
  38. classiq/model_expansions/arithmetic.py +6 -0
  39. classiq/qmod/builtins/functions/__init__.py +12 -9
  40. classiq/qmod/builtins/functions/allocation.py +0 -36
  41. classiq/qmod/builtins/functions/arithmetic.py +52 -0
  42. classiq/qmod/builtins/functions/gray_code.py +23 -0
  43. classiq/qmod/builtins/functions/mcx_func.py +10 -0
  44. classiq/qmod/builtins/structs.py +22 -3
  45. classiq/qprog_to_cudaq.py +347 -0
  46. {classiq-0.104.0.dist-info → classiq-1.0.0.dist-info}/METADATA +4 -1
  47. {classiq-0.104.0.dist-info → classiq-1.0.0.dist-info}/RECORD +52 -39
  48. /classiq/execution/functions/{_logging.py → util/_logging.py} +0 -0
  49. /classiq/execution/functions/{constants.py → util/constants.py} +0 -0
  50. /classiq/execution/functions/{parse_provider_backend.py → util/parse_provider_backend.py} +0 -0
  51. {classiq-0.104.0.dist-info → classiq-1.0.0.dist-info}/WHEEL +0 -0
  52. {classiq-0.104.0.dist-info → classiq-1.0.0.dist-info}/licenses/LICENSE.txt +0 -0
@@ -1,207 +1,26 @@
1
- from collections.abc import Callable
2
- from dataclasses import dataclass
3
- from typing import TYPE_CHECKING, Any, Literal
1
+ from typing import TYPE_CHECKING, Any
2
+
3
+ from classiq.execution.functions.util.backend_preferences import (
4
+ _get_backend_preferences_from_specifier,
5
+ )
4
6
 
5
7
  if TYPE_CHECKING:
6
8
  from pandas import DataFrame
7
9
 
8
- from classiq.interface.backend.backend_preferences import (
9
- AliceBobBackendPreferences,
10
- AQTBackendPreferences,
11
- AwsBackendPreferences,
12
- AzureBackendPreferences,
13
- AzureCredential,
14
- BackendPreferencesTypes,
15
- ClassiqBackendPreferences,
16
- GCPBackendPreferences,
17
- IBMBackendPreferences,
18
- IntelBackendPreferences,
19
- IonqBackendPreferences,
20
- )
21
10
  from classiq.interface.backend.provider_config.provider_config import ProviderConfig
22
- from classiq.interface.backend.provider_config.providers.alice_bob import AliceBobConfig
23
- from classiq.interface.backend.provider_config.providers.aqt import AQTConfig
24
- from classiq.interface.backend.provider_config.providers.azure import AzureConfig
25
- from classiq.interface.backend.provider_config.providers.braket import BraketConfig
26
- from classiq.interface.backend.provider_config.providers.ibm import IBMConfig
27
- from classiq.interface.backend.provider_config.providers.ionq import IonQConfig
28
- from classiq.interface.backend.quantum_backend_providers import (
29
- ClassiqNvidiaBackendNames,
30
- ClassiqSimulatorBackendNames,
31
- )
32
11
  from classiq.interface.executor.execution_preferences import ExecutionPreferences
33
12
  from classiq.interface.generator.model.preferences import create_random_seed
34
13
  from classiq.interface.generator.model.preferences.preferences import (
35
14
  TranspilationOption,
36
15
  )
37
- from classiq.interface.hardware import Provider
38
16
 
39
17
  from classiq import (
40
18
  ExecutionParams,
41
19
  QuantumProgram,
42
20
  )
43
21
  from classiq.execution import ExecutionSession
44
- from classiq.execution.functions._logging import _logger
45
- from classiq.execution.functions.constants import Verbosity
46
- from classiq.execution.functions.parse_provider_backend import (
47
- _PROVIDER_TO_CANONICAL_NAME,
48
- _parse_provider_backend,
49
- )
50
-
51
-
52
- @dataclass
53
- class _ProviderConfigToBackendPrefSpec:
54
- backend_preferences_class: type[BackendPreferencesTypes]
55
- config_class: type[ProviderConfig] | None = None
56
- # Maps the config dict (either passed in directly or dumped from config class) to a
57
- # dict that we can load into the given BackendPreferences class. This is in case
58
- # we need to rename fields or change structure.
59
- config_dict_to_backend_preferences_dict: (
60
- Callable[[dict[str, Any]], dict[str, Any]] | None
61
- ) = None
62
- # Maps from SDK names to names our backend recognizes, raising a useful error
63
- # if the name is unrecognized.
64
- backend_name_mapper: Callable[[str], str] | None = None
65
-
66
-
67
- def _classiq_backend_name_mapper(backend_name: str) -> str:
68
- backend_name = backend_name.lower()
69
- if backend_name in [
70
- ClassiqSimulatorBackendNames.SIMULATOR,
71
- ClassiqSimulatorBackendNames.SIMULATOR_MATRIX_PRODUCT_STATE,
72
- ClassiqSimulatorBackendNames.SIMULATOR_DENSITY_MATRIX,
73
- ]:
74
- return backend_name
75
- if backend_name == "nvidia_simulator":
76
- return ClassiqNvidiaBackendNames.SIMULATOR
77
- if any(keyword in backend_name for keyword in ["gpu", "nvidia"]):
78
- suggested_backend_name = "nvidia_simulator"
79
- else:
80
- suggested_backend_name = "simulator"
81
- raise ValueError(
82
- f"Unsupported backend name {backend_name}. Did you mean '{suggested_backend_name}'?"
83
- )
84
-
85
-
86
- def _ibm_backend_name_mapper(backend_name: str) -> str:
87
- ibm_prefix: Literal["ibm_"] = "ibm_"
88
- backend_name = backend_name.lower()
89
- if backend_name.startswith(ibm_prefix):
90
- backend_name_no_prefix = backend_name.removeprefix(ibm_prefix)
91
- raise ValueError(
92
- f"IBM backend names shouldn't start with ibm_. Try 'ibm/{backend_name_no_prefix}'."
93
- )
94
- return ibm_prefix + backend_name
95
-
96
-
97
- def _azure_config_dict_to_backend_preferences_dict(
98
- config_dict: dict[str, Any],
99
- ) -> dict[str, Any]:
100
- if "location" not in config_dict:
101
- raise ValueError("Azure config must have 'location' property")
102
- credentials = None
103
- if all(
104
- config_dict.get(key) is not None
105
- for key in ["tenant_id", "client_id", "client_secret", "resource_id"]
106
- ):
107
- credentials = AzureCredential.model_validate(
108
- {
109
- "tenant_id": config_dict["tenant_id"],
110
- "client_id": config_dict["client_id"],
111
- "client_secret": config_dict["client_secret"],
112
- "resource_id": config_dict["resource_id"],
113
- }
114
- )
115
- return {
116
- "location": config_dict["location"],
117
- "credentials": credentials,
118
- "ionq_error_mitigation_flag": config_dict.get("ionq_error_mitigation"),
119
- }
120
-
121
-
122
- def _braket_config_dict_to_backend_preferences_dict(
123
- config_dict: dict[str, Any],
124
- ) -> dict[str, Any]:
125
- config_dict["aws_access_key_id"] = config_dict.pop("braket_access_key_id", None)
126
- config_dict["aws_secret_access_key"] = config_dict.pop(
127
- "braket_secret_access_key", None
128
- )
129
- return config_dict
130
-
131
-
132
- _PROVIDER_CONFIG_TO_BACKEND_PREFERENCES_SPEC = {
133
- Provider.CLASSIQ: _ProviderConfigToBackendPrefSpec(
134
- backend_preferences_class=ClassiqBackendPreferences,
135
- backend_name_mapper=_classiq_backend_name_mapper,
136
- ),
137
- Provider.GOOGLE: _ProviderConfigToBackendPrefSpec(
138
- backend_preferences_class=GCPBackendPreferences
139
- ),
140
- Provider.INTEL: _ProviderConfigToBackendPrefSpec(
141
- backend_preferences_class=IntelBackendPreferences
142
- ),
143
- Provider.IBM_QUANTUM: _ProviderConfigToBackendPrefSpec(
144
- backend_preferences_class=IBMBackendPreferences,
145
- config_class=IBMConfig,
146
- backend_name_mapper=_ibm_backend_name_mapper,
147
- ),
148
- Provider.AMAZON_BRAKET: _ProviderConfigToBackendPrefSpec(
149
- backend_preferences_class=AwsBackendPreferences,
150
- config_dict_to_backend_preferences_dict=_braket_config_dict_to_backend_preferences_dict,
151
- config_class=BraketConfig,
152
- ),
153
- Provider.IONQ: _ProviderConfigToBackendPrefSpec(
154
- backend_preferences_class=IonqBackendPreferences,
155
- config_class=IonQConfig,
156
- ),
157
- Provider.ALICE_AND_BOB: _ProviderConfigToBackendPrefSpec(
158
- backend_preferences_class=AliceBobBackendPreferences,
159
- config_class=AliceBobConfig,
160
- ),
161
- Provider.AQT: _ProviderConfigToBackendPrefSpec(
162
- backend_preferences_class=AQTBackendPreferences,
163
- config_class=AQTConfig,
164
- ),
165
- Provider.AZURE_QUANTUM: _ProviderConfigToBackendPrefSpec(
166
- backend_preferences_class=AzureBackendPreferences,
167
- config_dict_to_backend_preferences_dict=_azure_config_dict_to_backend_preferences_dict,
168
- config_class=AzureConfig,
169
- ),
170
- }
171
-
172
-
173
- def _get_backend_preferences_from_specifier(
174
- backend_spec: str, config: dict[str, Any] | ProviderConfig
175
- ) -> BackendPreferencesTypes:
176
- provider, backend_name = _parse_provider_backend(backend_spec)
177
-
178
- if provider not in _PROVIDER_CONFIG_TO_BACKEND_PREFERENCES_SPEC:
179
- raise NotImplementedError(
180
- f"Unsupported provider '{_PROVIDER_TO_CANONICAL_NAME.get(provider) or provider}'"
181
- )
182
-
183
- provider_spec = _PROVIDER_CONFIG_TO_BACKEND_PREFERENCES_SPEC[provider]
184
- if isinstance(config, ProviderConfig):
185
- if provider_spec.config_class is None:
186
- raise ValueError(
187
- f"This provider does not support any ProviderConfig classes. Received '{config.__class__.__name__}'"
188
- )
189
- if not isinstance(config, provider_spec.config_class):
190
- raise ValueError(
191
- f"{_PROVIDER_TO_CANONICAL_NAME[provider]} devices require {provider_spec.config_class.__name__}, got {config.__class__.__name__}"
192
- )
193
- config_dict = config.model_dump()
194
- else:
195
- config_dict = config
196
- if provider_spec.backend_name_mapper is not None:
197
- backend_name = provider_spec.backend_name_mapper(backend_name)
198
-
199
- if provider_spec.config_dict_to_backend_preferences_dict is not None:
200
- config_dict = provider_spec.config_dict_to_backend_preferences_dict(config_dict)
201
-
202
- config_dict["backend_name"] = backend_name
203
- return provider_spec.backend_preferences_class.model_validate(config_dict)
204
-
22
+ from classiq.execution.functions.util._logging import _logger
23
+ from classiq.execution.functions.util.constants import Verbosity
205
24
 
206
25
  _DEFAULT_BACKEND_NAME = "simulator"
207
26
 
@@ -222,7 +41,7 @@ def _new_sample(
222
41
 
223
42
  Args:
224
43
  qprog: The quantum program
225
- backend: The device (hardware or simulator) on which to run the quantum program. Specified as "provider/device_id"
44
+ backend: The device (hardware or simulator) on which to run the quantum program. Specified as "provider/device_id". Use the `get_backend_details` function to see supported devices.
226
45
  parameters: The classical parameters for the quantum program
227
46
  config: Provider-specific configuration, such as api keys
228
47
  num_shots: The number of times to sample
@@ -0,0 +1,113 @@
1
+ from typing import TYPE_CHECKING, Any
2
+
3
+ if TYPE_CHECKING:
4
+ from pandas import DataFrame
5
+
6
+ from classiq.interface.backend.backend_preferences import (
7
+ BackendPreferencesTypes,
8
+ ClassiqBackendPreferences,
9
+ GCPBackendPreferences,
10
+ )
11
+ from classiq.interface.backend.quantum_backend_providers import (
12
+ ClassiqNvidiaBackendNames,
13
+ ClassiqSimulatorBackendNames,
14
+ GoogleNvidiaBackendNames,
15
+ )
16
+ from classiq.interface.executor.execution_preferences import ExecutionPreferences
17
+ from classiq.interface.generator.model.preferences import create_random_seed
18
+ from classiq.interface.generator.model.preferences.preferences import (
19
+ TranspilationOption,
20
+ )
21
+ from classiq.interface.hardware import Provider
22
+
23
+ from classiq import (
24
+ ExecutionParams,
25
+ QuantumProgram,
26
+ )
27
+ from classiq.execution import ExecutionSession
28
+ from classiq.execution.functions.util._logging import _logger
29
+ from classiq.execution.functions.util.constants import Verbosity
30
+ from classiq.execution.functions.util.parse_provider_backend import (
31
+ _PROVIDER_TO_CANONICAL_NAME,
32
+ _parse_provider_backend,
33
+ )
34
+
35
+ _DEFAULT_STATE_VECTOR_BACKEND_NAME = "simulator"
36
+
37
+
38
+ def _calculate_state_vector(
39
+ qprog: QuantumProgram,
40
+ backend: str | None = None,
41
+ *,
42
+ parameters: ExecutionParams | None = None,
43
+ filters: dict[str, Any] | None = None,
44
+ random_seed: int | None = None,
45
+ transpilation_option: TranspilationOption = TranspilationOption.DECOMPOSE,
46
+ verbosity: Verbosity = Verbosity.INFO,
47
+ ) -> "DataFrame":
48
+ """
49
+ Calculate the state vector of a quantum program.
50
+
51
+ Args:
52
+ qprog: The quantum program
53
+ backend: The simulator on which to simulate the quantum program. Specified as "provider/device_id"
54
+ parameters: The classical parameters for the quantum program
55
+ filters: Only states where the variables match these values will be included in the state vector.
56
+ random_seed: The random seed used for transpilation and simulation
57
+ transpilation_option: Advanced configuration for hardware-specific transpilation
58
+ verbosity: What level of information should be logged
59
+
60
+ Returns: A dataframe containing the state vector
61
+ """
62
+ if backend is None:
63
+ backend = _DEFAULT_STATE_VECTOR_BACKEND_NAME
64
+
65
+ provider, raw_backend_name = _parse_provider_backend(backend)
66
+ backend_name_lower = raw_backend_name.lower()
67
+ backend_preferences: BackendPreferencesTypes
68
+
69
+ if provider == Provider.CLASSIQ:
70
+ if backend_name_lower == "simulator":
71
+ backend_name = str(ClassiqSimulatorBackendNames.SIMULATOR_STATEVECTOR)
72
+ elif backend_name_lower == "nvidia_simulator":
73
+ backend_name = str(ClassiqNvidiaBackendNames.SIMULATOR_STATEVECTOR)
74
+ else:
75
+ raise ValueError(
76
+ f"Unsupported backend '{backend}'. "
77
+ "Under the Classiq provider, only 'classiq/simulator' and 'classiq/nvidia_simulator' are supported."
78
+ )
79
+ backend_preferences = ClassiqBackendPreferences(backend_name=backend_name)
80
+ elif provider == Provider.GOOGLE:
81
+ if backend_name_lower == "cuquantum":
82
+ backend_name = str(GoogleNvidiaBackendNames.CUQUANTUM_STATEVECTOR)
83
+ else:
84
+ raise ValueError(
85
+ f"Unsupported backend '{backend}'. "
86
+ "Under the Google provider, only 'google/cuquantum' is supported."
87
+ )
88
+ backend_preferences = GCPBackendPreferences(backend_name=backend_name)
89
+ else:
90
+ raise ValueError(
91
+ f"Provider '{_PROVIDER_TO_CANONICAL_NAME.get(provider) or provider}' does not support this operation."
92
+ )
93
+
94
+ ep = ExecutionPreferences(
95
+ backend_preferences=backend_preferences,
96
+ random_seed=create_random_seed() if random_seed is None else random_seed,
97
+ transpile_to_hardware=transpilation_option,
98
+ )
99
+ if verbosity != Verbosity.QUIET:
100
+ _logger.info(f"Submitting job to {backend}")
101
+ with ExecutionSession(qprog, execution_preferences=ep) as session:
102
+ if filters is not None:
103
+ for output_name, value in filters.items():
104
+ session.set_measured_state_filter(
105
+ output_name, lambda state, val=value: state == val
106
+ )
107
+ job = session.submit_sample(parameters)
108
+ if verbosity != Verbosity.QUIET:
109
+ _logger.info(f"Job id: {job.id}")
110
+ result = job.get_sample_result()
111
+
112
+ df = result.dataframe
113
+ return df
File without changes
@@ -0,0 +1,188 @@
1
+ from collections.abc import Callable
2
+ from dataclasses import dataclass
3
+ from typing import Any, Literal
4
+
5
+ from classiq.interface.backend.backend_preferences import (
6
+ AliceBobBackendPreferences,
7
+ AQTBackendPreferences,
8
+ AwsBackendPreferences,
9
+ AzureBackendPreferences,
10
+ AzureCredential,
11
+ BackendPreferencesTypes,
12
+ ClassiqBackendPreferences,
13
+ GCPBackendPreferences,
14
+ IBMBackendPreferences,
15
+ IntelBackendPreferences,
16
+ IonqBackendPreferences,
17
+ )
18
+ from classiq.interface.backend.provider_config.provider_config import ProviderConfig
19
+ from classiq.interface.backend.provider_config.providers.alice_bob import AliceBobConfig
20
+ from classiq.interface.backend.provider_config.providers.aqt import AQTConfig
21
+ from classiq.interface.backend.provider_config.providers.azure import AzureConfig
22
+ from classiq.interface.backend.provider_config.providers.braket import BraketConfig
23
+ from classiq.interface.backend.provider_config.providers.ibm import IBMConfig
24
+ from classiq.interface.backend.provider_config.providers.ionq import IonQConfig
25
+ from classiq.interface.backend.quantum_backend_providers import (
26
+ ClassiqNvidiaBackendNames,
27
+ ClassiqSimulatorBackendNames,
28
+ )
29
+ from classiq.interface.hardware import Provider
30
+
31
+ from classiq.execution.functions.util.parse_provider_backend import (
32
+ _PROVIDER_TO_CANONICAL_NAME,
33
+ _parse_provider_backend,
34
+ )
35
+
36
+
37
+ @dataclass
38
+ class _ProviderConfigToBackendPrefSpec:
39
+ backend_preferences_class: type[BackendPreferencesTypes]
40
+ config_class: type[ProviderConfig] | None = None
41
+ # Maps the config dict (either passed in directly or dumped from config class) to a
42
+ # dict that we can load into the given BackendPreferences class. This is in case
43
+ # we need to rename fields or change structure.
44
+ config_dict_to_backend_preferences_dict: (
45
+ Callable[[dict[str, Any]], dict[str, Any]] | None
46
+ ) = None
47
+ # Maps from SDK names to names our backend recognizes, raising a useful error
48
+ # if the name is unrecognized.
49
+ backend_name_mapper: Callable[[str], str] | None = None
50
+
51
+
52
+ def _classiq_backend_name_mapper(backend_name: str) -> str:
53
+ backend_name = backend_name.lower()
54
+ if backend_name in [
55
+ ClassiqSimulatorBackendNames.SIMULATOR,
56
+ ClassiqSimulatorBackendNames.SIMULATOR_MATRIX_PRODUCT_STATE,
57
+ ClassiqSimulatorBackendNames.SIMULATOR_DENSITY_MATRIX,
58
+ ]:
59
+ return backend_name
60
+ if backend_name == "nvidia_simulator":
61
+ return ClassiqNvidiaBackendNames.SIMULATOR
62
+ if any(keyword in backend_name for keyword in ["gpu", "nvidia"]):
63
+ suggested_backend_name = "nvidia_simulator"
64
+ else:
65
+ suggested_backend_name = "simulator"
66
+ raise ValueError(
67
+ f"Unsupported backend name {backend_name}. Did you mean '{suggested_backend_name}'?"
68
+ )
69
+
70
+
71
+ def _ibm_backend_name_mapper(backend_name: str) -> str:
72
+ ibm_prefix: Literal["ibm_"] = "ibm_"
73
+ backend_name = backend_name.lower()
74
+ if backend_name.startswith(ibm_prefix):
75
+ backend_name_no_prefix = backend_name.removeprefix(ibm_prefix)
76
+ raise ValueError(
77
+ f"IBM backend names shouldn't start with ibm_. Try 'ibm/{backend_name_no_prefix}'."
78
+ )
79
+ return ibm_prefix + backend_name
80
+
81
+
82
+ def _azure_config_dict_to_backend_preferences_dict(
83
+ config_dict: dict[str, Any],
84
+ ) -> dict[str, Any]:
85
+ if "location" not in config_dict:
86
+ raise ValueError("Azure config must have 'location' property")
87
+ credentials = None
88
+ if all(
89
+ config_dict.get(key) is not None
90
+ for key in ["tenant_id", "client_id", "client_secret", "resource_id"]
91
+ ):
92
+ credentials = AzureCredential.model_validate(
93
+ {
94
+ "tenant_id": config_dict["tenant_id"],
95
+ "client_id": config_dict["client_id"],
96
+ "client_secret": config_dict["client_secret"],
97
+ "resource_id": config_dict["resource_id"],
98
+ }
99
+ )
100
+ return {
101
+ "location": config_dict["location"],
102
+ "credentials": credentials,
103
+ "ionq_error_mitigation_flag": config_dict.get("ionq_error_mitigation"),
104
+ }
105
+
106
+
107
+ def _braket_config_dict_to_backend_preferences_dict(
108
+ config_dict: dict[str, Any],
109
+ ) -> dict[str, Any]:
110
+ config_dict["aws_access_key_id"] = config_dict.pop("braket_access_key_id", None)
111
+ config_dict["aws_secret_access_key"] = config_dict.pop(
112
+ "braket_secret_access_key", None
113
+ )
114
+ return config_dict
115
+
116
+
117
+ _PROVIDER_CONFIG_TO_BACKEND_PREFERENCES_SPEC = {
118
+ Provider.CLASSIQ: _ProviderConfigToBackendPrefSpec(
119
+ backend_preferences_class=ClassiqBackendPreferences,
120
+ backend_name_mapper=_classiq_backend_name_mapper,
121
+ ),
122
+ Provider.GOOGLE: _ProviderConfigToBackendPrefSpec(
123
+ backend_preferences_class=GCPBackendPreferences
124
+ ),
125
+ Provider.INTEL: _ProviderConfigToBackendPrefSpec(
126
+ backend_preferences_class=IntelBackendPreferences
127
+ ),
128
+ Provider.IBM_QUANTUM: _ProviderConfigToBackendPrefSpec(
129
+ backend_preferences_class=IBMBackendPreferences,
130
+ config_class=IBMConfig,
131
+ backend_name_mapper=_ibm_backend_name_mapper,
132
+ ),
133
+ Provider.AMAZON_BRAKET: _ProviderConfigToBackendPrefSpec(
134
+ backend_preferences_class=AwsBackendPreferences,
135
+ config_dict_to_backend_preferences_dict=_braket_config_dict_to_backend_preferences_dict,
136
+ config_class=BraketConfig,
137
+ ),
138
+ Provider.IONQ: _ProviderConfigToBackendPrefSpec(
139
+ backend_preferences_class=IonqBackendPreferences,
140
+ config_class=IonQConfig,
141
+ ),
142
+ Provider.ALICE_AND_BOB: _ProviderConfigToBackendPrefSpec(
143
+ backend_preferences_class=AliceBobBackendPreferences,
144
+ config_class=AliceBobConfig,
145
+ ),
146
+ Provider.AQT: _ProviderConfigToBackendPrefSpec(
147
+ backend_preferences_class=AQTBackendPreferences,
148
+ config_class=AQTConfig,
149
+ ),
150
+ Provider.AZURE_QUANTUM: _ProviderConfigToBackendPrefSpec(
151
+ backend_preferences_class=AzureBackendPreferences,
152
+ config_dict_to_backend_preferences_dict=_azure_config_dict_to_backend_preferences_dict,
153
+ config_class=AzureConfig,
154
+ ),
155
+ }
156
+
157
+
158
+ def _get_backend_preferences_from_specifier(
159
+ backend_spec: str, config: dict[str, Any] | ProviderConfig
160
+ ) -> BackendPreferencesTypes:
161
+ provider, backend_name = _parse_provider_backend(backend_spec)
162
+
163
+ if provider not in _PROVIDER_CONFIG_TO_BACKEND_PREFERENCES_SPEC:
164
+ raise NotImplementedError(
165
+ f"Unsupported provider '{_PROVIDER_TO_CANONICAL_NAME.get(provider) or provider}'"
166
+ )
167
+
168
+ provider_spec = _PROVIDER_CONFIG_TO_BACKEND_PREFERENCES_SPEC[provider]
169
+ if isinstance(config, ProviderConfig):
170
+ if provider_spec.config_class is None:
171
+ raise ValueError(
172
+ f"This provider does not support any ProviderConfig classes. Received '{config.__class__.__name__}'"
173
+ )
174
+ if not isinstance(config, provider_spec.config_class):
175
+ raise ValueError(
176
+ f"{_PROVIDER_TO_CANONICAL_NAME[provider]} devices require {provider_spec.config_class.__name__}, got {config.__class__.__name__}"
177
+ )
178
+ config_dict = config.model_dump()
179
+ else:
180
+ config_dict = config
181
+ if provider_spec.backend_name_mapper is not None:
182
+ backend_name = provider_spec.backend_name_mapper(backend_name)
183
+
184
+ if provider_spec.config_dict_to_backend_preferences_dict is not None:
185
+ config_dict = provider_spec.config_dict_to_backend_preferences_dict(config_dict)
186
+
187
+ config_dict["backend_name"] = backend_name
188
+ return provider_spec.backend_preferences_class.model_validate(config_dict)
@@ -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.104.0'
6
+ SEMVER_VERSION = '1.0.0'
7
7
  VERSION = str(Version(SEMVER_VERSION))
@@ -468,6 +468,70 @@ class SoftbankBackendPreferences(BackendPreferences):
468
468
  )
469
469
 
470
470
 
471
+ class C12BackendPreferences(BackendPreferences):
472
+ """
473
+ Represents the backend preferences specific to C12.
474
+
475
+ Attributes:
476
+ backend_name: Name of the requested backend or target.
477
+ result_format: Result format of the job; one of "counts",
478
+ "state_vector", or "density_matrix". Defaults to "counts".
479
+ inilabel: Initial state specified using a binary label format
480
+ (e.g. "00", "01"). Mutually exclusive with inistatevector.
481
+ inistatevector: Initial state vector as a comma-separated list of
482
+ complex values (e.g. "1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j").
483
+ Mutually exclusive with inilabel.
484
+ ininoisy: Whether to use noisy initialization of the circuit.
485
+ """
486
+
487
+ backend_service_provider: ProviderTypeVendor.C12 = pydantic.Field(
488
+ default=ProviderVendor.C12
489
+ )
490
+
491
+ result_format: str = pydantic.Field(
492
+ default="counts", description="Result format of the job"
493
+ )
494
+
495
+ inilabel: str | None = pydantic.Field(
496
+ default=None, description="Initial label of the initial state."
497
+ )
498
+
499
+ inistatevector: str | None = pydantic.Field(
500
+ default=None, description="Initial state vector of the job."
501
+ )
502
+
503
+ ininoisy: bool | None = pydantic.Field(
504
+ default=None, description="Whether the initial state is noisy."
505
+ )
506
+
507
+ @pydantic.model_validator(mode="after")
508
+ def _validate_initial_label_statevector(
509
+ self: C12BackendPreferences,
510
+ ) -> C12BackendPreferences:
511
+ if self.inilabel is not None and self.inistatevector is not None:
512
+ raise ValueError(
513
+ f"Cannot specify both inilabel and inistatevector.\n"
514
+ f"inilabel={self.inilabel}, inistatevector={self.inistatevector}"
515
+ )
516
+ return self
517
+
518
+ @pydantic.field_validator("result_format")
519
+ @classmethod
520
+ def _validate_result_format(cls, result_format: str) -> str:
521
+ if result_format not in ["density_matrix", "state_vector", "counts"]:
522
+ raise ValueError(f"Invalid result format: {result_format}")
523
+ return result_format
524
+
525
+ @property
526
+ def parameters(self) -> dict:
527
+ data = self.model_dump(exclude_none=True)
528
+ for field in ["inilabel", "inistatevector", "ininoisy"]:
529
+ if field in data and data[field] is None:
530
+ data.pop(field)
531
+
532
+ return data
533
+
534
+
471
535
  def is_exact_simulator(backend_preferences: BackendPreferences) -> bool:
472
536
  return backend_preferences.backend_name in EXACT_SIMULATORS
473
537
 
@@ -501,6 +565,7 @@ BackendPreferencesTypes = Union[
501
565
  AQTBackendPreferences,
502
566
  CINECABackendPreferences,
503
567
  SoftbankBackendPreferences,
568
+ C12BackendPreferences,
504
569
  ]
505
570
 
506
571
  __all__ = [
@@ -512,6 +577,7 @@ __all__ = [
512
577
  "AzureBackendPreferences",
513
578
  "AzureCredential",
514
579
  "AzureQuantumBackendNames",
580
+ "C12BackendPreferences",
515
581
  "ClassiqBackendPreferences",
516
582
  "ClassiqNvidiaBackendNames",
517
583
  "ClassiqSimulatorBackendNames",
@@ -28,6 +28,7 @@ class ProviderVendor(StrEnum):
28
28
  AQT = "AQT"
29
29
  CINECA = "CINECA"
30
30
  SOFTBANK = "Softbank"
31
+ C12 = "C12"
31
32
 
32
33
 
33
34
  class ProviderTypeVendor:
@@ -43,6 +44,7 @@ class ProviderTypeVendor:
43
44
  AQT = Literal[ProviderVendor.AQT]
44
45
  CINECA = Literal[ProviderVendor.CINECA]
45
46
  SOFTBANK = Literal[ProviderVendor.SOFTBANK]
47
+ C12 = Literal[ProviderVendor.C12]
46
48
 
47
49
 
48
50
  PROVIDER_NAME_MAPPER = {
@@ -57,6 +59,7 @@ PROVIDER_NAME_MAPPER = {
57
59
  ProviderVendor.AQT: "AQT",
58
60
  ProviderVendor.CLASSIQ: "CLASSIQ",
59
61
  ProviderVendor.SOFTBANK: "SOFTBANK",
62
+ ProviderVendor.C12: "C12",
60
63
  }
61
64
 
62
65
 
@@ -248,6 +251,11 @@ class OQCBackendNames(StrEnum):
248
251
  LUCY = "Lucy"
249
252
 
250
253
 
254
+ class C12BackendNames(StrEnum):
255
+ SIMULATOR = "c12sim-iswap"
256
+ SQUARED = "squared-iswap"
257
+
258
+
251
259
  EXACT_SIMULATORS = {
252
260
  IonqBackendNames.SIMULATOR,
253
261
  AzureQuantumBackendNames.IONQ_SIMULATOR,
@@ -258,6 +266,7 @@ EXACT_SIMULATORS = {
258
266
  *ClassiqSimulatorBackendNames,
259
267
  *IntelBackendNames,
260
268
  *ClassiqNvidiaBackendNames,
269
+ *C12BackendNames,
261
270
  }
262
271
 
263
272
  AllIBMQBackendNames = IBMQHardwareNames
@@ -271,6 +280,7 @@ AllBackendsNameByVendor = Union[
271
280
  ClassiqNvidiaBackendNames,
272
281
  AliceBobBackendNames,
273
282
  OQCBackendNames,
283
+ C12BackendNames,
274
284
  ]
275
285
 
276
286
  AllBackendsNameEnums = [
@@ -282,4 +292,5 @@ AllBackendsNameEnums = [
282
292
  IntelBackendNames,
283
293
  ClassiqNvidiaBackendNames,
284
294
  OQCBackendNames,
295
+ C12BackendNames,
285
296
  ]
@@ -39,10 +39,6 @@ class ClassiqAnalyzerError(ClassiqError):
39
39
  pass
40
40
 
41
41
 
42
- class ClassiqAnalyzerVisualizationError(ClassiqError):
43
- pass
44
-
45
-
46
42
  class ClassiqAPIError(ClassiqError):
47
43
  def __init__(self, message: str, status_code: int | None = None) -> None:
48
44
  self.status_code = status_code