qilisdk 0.1.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 (47) hide show
  1. qilisdk/__init__.py +47 -0
  2. qilisdk/__init__.pyi +30 -0
  3. qilisdk/_optionals.py +105 -0
  4. qilisdk/analog/__init__.py +17 -0
  5. qilisdk/analog/algorithms.py +111 -0
  6. qilisdk/analog/analog_backend.py +43 -0
  7. qilisdk/analog/analog_result.py +114 -0
  8. qilisdk/analog/exceptions.py +19 -0
  9. qilisdk/analog/hamiltonian.py +706 -0
  10. qilisdk/analog/quantum_objects.py +486 -0
  11. qilisdk/analog/schedule.py +311 -0
  12. qilisdk/common/__init__.py +20 -0
  13. qilisdk/common/algorithm.py +17 -0
  14. qilisdk/common/backend.py +16 -0
  15. qilisdk/common/model.py +16 -0
  16. qilisdk/common/optimizer.py +136 -0
  17. qilisdk/common/optimizer_result.py +110 -0
  18. qilisdk/common/result.py +17 -0
  19. qilisdk/digital/__init__.py +66 -0
  20. qilisdk/digital/ansatz.py +143 -0
  21. qilisdk/digital/circuit.py +106 -0
  22. qilisdk/digital/digital_algorithm.py +20 -0
  23. qilisdk/digital/digital_backend.py +90 -0
  24. qilisdk/digital/digital_result.py +145 -0
  25. qilisdk/digital/exceptions.py +31 -0
  26. qilisdk/digital/gates.py +989 -0
  27. qilisdk/digital/vqe.py +165 -0
  28. qilisdk/extras/__init__.py +13 -0
  29. qilisdk/extras/cuda/__init__.py +18 -0
  30. qilisdk/extras/cuda/cuda_analog_result.py +19 -0
  31. qilisdk/extras/cuda/cuda_backend.py +398 -0
  32. qilisdk/extras/cuda/cuda_digital_result.py +19 -0
  33. qilisdk/extras/qaas/__init__.py +13 -0
  34. qilisdk/extras/qaas/keyring.py +54 -0
  35. qilisdk/extras/qaas/models.py +57 -0
  36. qilisdk/extras/qaas/qaas_backend.py +154 -0
  37. qilisdk/extras/qaas/qaas_digital_result.py +20 -0
  38. qilisdk/extras/qaas/qaas_settings.py +23 -0
  39. qilisdk/py.typed +0 -0
  40. qilisdk/utils/__init__.py +27 -0
  41. qilisdk/utils/openqasm2.py +215 -0
  42. qilisdk/utils/serialization.py +128 -0
  43. qilisdk/yaml.py +71 -0
  44. qilisdk-0.1.0.dist-info/METADATA +237 -0
  45. qilisdk-0.1.0.dist-info/RECORD +47 -0
  46. qilisdk-0.1.0.dist-info/WHEEL +4 -0
  47. qilisdk-0.1.0.dist-info/licenses/LICENCE +201 -0
@@ -0,0 +1,66 @@
1
+ # Copyright 2025 Qilimanjaro Quantum Tech
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ from .circuit import Circuit
16
+ from .digital_backend import DigitalBackend, DigitalSimulationMethod
17
+ from .digital_result import DigitalResult
18
+ from .gates import (
19
+ CNOT,
20
+ CZ,
21
+ RX,
22
+ RY,
23
+ RZ,
24
+ U1,
25
+ U2,
26
+ U3,
27
+ Adjoint,
28
+ BasicGate,
29
+ Controlled,
30
+ Exponential,
31
+ Gate,
32
+ H,
33
+ M,
34
+ S,
35
+ T,
36
+ X,
37
+ Y,
38
+ Z,
39
+ )
40
+
41
+ __all__ = [
42
+ "CNOT",
43
+ "CZ",
44
+ "RX",
45
+ "RY",
46
+ "RZ",
47
+ "U1",
48
+ "U2",
49
+ "U3",
50
+ "Adjoint",
51
+ "BasicGate",
52
+ "Circuit",
53
+ "Controlled",
54
+ "DigitalBackend",
55
+ "DigitalResult",
56
+ "DigitalSimulationMethod",
57
+ "Exponential",
58
+ "Gate",
59
+ "H",
60
+ "M",
61
+ "S",
62
+ "T",
63
+ "X",
64
+ "Y",
65
+ "Z",
66
+ ]
@@ -0,0 +1,143 @@
1
+ # Copyright 2025 Qilimanjaro Quantum Tech
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ from abc import ABC, abstractmethod
15
+ from typing import ClassVar, Literal, Union
16
+
17
+ from qilisdk.digital.circuit import Circuit
18
+ from qilisdk.digital.gates import CNOT, CZ, U1, U2, U3, M
19
+ from qilisdk.yaml import yaml
20
+
21
+
22
+ class Ansatz(ABC):
23
+ _ONE_QUBIT_GATES: ClassVar[dict[str, type[Union[U1, U2, U3]]]] = {
24
+ "U1": U1,
25
+ "U2": U2,
26
+ "U3": U3,
27
+ }
28
+ _TWO_QUBITS_GATES: ClassVar[dict[str, type[Union[CNOT, CZ]]]] = {
29
+ "CZ": CZ,
30
+ "CNOT": CNOT,
31
+ }
32
+
33
+ def __init__(self, nqubits: int, layers: int = 1) -> None:
34
+ self.nqubits = nqubits
35
+ self.layers = layers
36
+
37
+ @property
38
+ def nparameters(self) -> int:
39
+ """
40
+ Retrieve the total number of parameters required by all parameterized gates in the ansatz's circuit.
41
+
42
+ Returns:
43
+ int: The total count of parameters from all parameterized gates.
44
+ """
45
+ raise NotImplementedError
46
+
47
+ def get_circuit(self, parameters: list[float]) -> Circuit:
48
+ """Get the underlying circuit with the given list of parameters.
49
+
50
+ Args:
51
+ params (list[float]): the list of parameters for the unitary gates.
52
+
53
+ Raises:
54
+ ValueError: if the number of parameters provided are less than the parameters expected by the ansatz.
55
+
56
+ Returns:
57
+ Circuit: The underlying circuit with the updated parameters.
58
+ """
59
+ if len(parameters) != self.nparameters:
60
+ raise ValueError(f"Expecting {self.nparameters} but received {len(parameters)}")
61
+
62
+ return self._construct_circuit(parameters=list(parameters))
63
+
64
+ @abstractmethod
65
+ def _construct_circuit(self, parameters: list[float]) -> Circuit: ...
66
+
67
+
68
+ @yaml.register_class
69
+ class HardwareEfficientAnsatz(Ansatz):
70
+ def __init__(
71
+ self,
72
+ n_qubits: int,
73
+ layers: int = 1,
74
+ connectivity: Literal["Circular", "Linear", "Full"] | list[tuple[int, int]] = "Linear",
75
+ structure: Literal["grouped", "interposed"] = "grouped",
76
+ one_qubit_gate: Literal["U1", "U2", "U3"] = "U1",
77
+ two_qubit_gate: Literal["CZ", "CNOT"] = "CZ",
78
+ ) -> None:
79
+ super().__init__(n_qubits, layers)
80
+
81
+ # Define chip topology
82
+ if isinstance(connectivity, list):
83
+ self.connectivity = connectivity
84
+ elif connectivity == "Full":
85
+ self.connectivity = [(i, j) for i in range(self.nqubits) for j in range(i + 1, self.nqubits)]
86
+ elif connectivity == "Circular":
87
+ self.connectivity = [(i, i + 1) for i in range(self.nqubits - 1)] + [(self.nqubits - 1, 0)]
88
+ elif connectivity == "Linear":
89
+ self.connectivity = [(i, i + 1) for i in range(self.nqubits - 1)]
90
+ else:
91
+ raise ValueError(f"Unrecognized connectivity type ({connectivity}).")
92
+
93
+ self.gate_types: dict[str, str] = {"one_qubit_gate": one_qubit_gate, "two_qubit_gates": two_qubit_gate}
94
+ self.one_qubit_gate: type[Union[U1, U2, U3]] = self._ONE_QUBIT_GATES[one_qubit_gate]
95
+ self.two_qubit_gate: type[Union[CNOT, CZ]] = self._TWO_QUBITS_GATES[two_qubit_gate]
96
+
97
+ if structure not in {"grouped", "interposed"}:
98
+ raise ValueError(f"provided structure {structure} is not supported.")
99
+ self.structure = structure
100
+
101
+ self.construct_layer_handlers = {
102
+ "interposed": self._construct_layer_interposed,
103
+ "grouped": self._construct_layer_grouped,
104
+ }
105
+
106
+ @property
107
+ def nparameters(self) -> int:
108
+ """
109
+ Retrieve the total number of parameters required by all parameterized gates in the ansatz's circuit.
110
+
111
+ Returns:
112
+ int: The total count of parameters from all parameterized gates.
113
+ """
114
+ return self.nqubits * (self.layers + 1) * len(self.one_qubit_gate.PARAMETER_NAMES)
115
+
116
+ def _construct_circuit(self, parameters: list[float]) -> Circuit:
117
+ self._circuit = Circuit(self.nqubits)
118
+ # Add initial layer of unitaries
119
+ for i in range(self.nqubits):
120
+ self._circuit.add(self.one_qubit_gate(i, **dict(zip(self.one_qubit_gate.PARAMETER_NAMES, parameters))))
121
+
122
+ construct_layer_handler = self.construct_layer_handlers[self.structure]
123
+ for _ in range(self.layers):
124
+ construct_layer_handler(parameters)
125
+ self._circuit.add(M(*list(range(self.nqubits))))
126
+
127
+ return self._circuit
128
+
129
+ def _construct_layer_interposed(self, parameters: list[float]) -> None:
130
+ for i in range(self.nqubits):
131
+ self._circuit.add(
132
+ self.one_qubit_gate(i, **{name: parameters.pop() for name in self.one_qubit_gate.PARAMETER_NAMES})
133
+ )
134
+ for p, j in self.connectivity:
135
+ self._circuit.add(self.two_qubit_gate(p, j))
136
+
137
+ def _construct_layer_grouped(self, parameters: list[float]) -> None:
138
+ for i in range(self.nqubits):
139
+ self._circuit.add(
140
+ self.one_qubit_gate(i, **{name: parameters.pop() for name in self.one_qubit_gate.PARAMETER_NAMES})
141
+ )
142
+ for i, j in self.connectivity:
143
+ self._circuit.add(self.two_qubit_gate(i, j))
@@ -0,0 +1,106 @@
1
+ # Copyright 2025 Qilimanjaro Quantum Tech
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ import numpy as np
15
+
16
+ from qilisdk.yaml import yaml
17
+
18
+ from .exceptions import ParametersNotEqualError, QubitOutOfRangeError
19
+ from .gates import Gate
20
+
21
+
22
+ @yaml.register_class
23
+ class Circuit:
24
+ def __init__(self, nqubits: int) -> None:
25
+ """
26
+ Initialize a Circuit instance with a specified number of qubits.
27
+
28
+ Args:
29
+ nqubits (int): The number of qubits in the circuit.
30
+ """
31
+ self._nqubits: int = nqubits
32
+ self._gates: list[Gate] = []
33
+ self._init_state: np.ndarray = np.zeros(nqubits)
34
+ self._parameterized_gates: list[Gate] = []
35
+
36
+ @property
37
+ def nqubits(self) -> int:
38
+ """
39
+ Retrieve the number of qubits in the circuit.
40
+
41
+ Returns:
42
+ int: The total number of qubits.
43
+ """
44
+ return self._nqubits
45
+
46
+ @property
47
+ def nparameters(self) -> int:
48
+ """
49
+ Retrieve the total number of parameters required by all parameterized gates in the circuit.
50
+
51
+ Returns:
52
+ int: The total count of parameters from all parameterized gates.
53
+ """
54
+ return len([value for gate in self._gates if gate.is_parameterized for value in gate.parameter_values])
55
+
56
+ @property
57
+ def gates(self) -> list[Gate]:
58
+ """
59
+ Retrieve the list of gates in the circuit.
60
+
61
+ Returns:
62
+ list[Gate]: A list of gates that have been added to the circuit.
63
+ """
64
+ return self._gates
65
+
66
+ def get_parameter_values(self) -> list[float]:
67
+ """
68
+ Retrieve the parameter values from all parameterized gates in the circuit.
69
+
70
+ Returns:
71
+ list[float]: A list of parameter values from each parameterized gate.
72
+ """
73
+ return [value for gate in self._gates if gate.is_parameterized for value in gate.parameter_values]
74
+
75
+ def set_parameter_values(self, values: list[float]) -> None:
76
+ """
77
+ Set new parameter values for all parameterized gates in the circuit.
78
+
79
+ Args:
80
+ values (list[float]): A list containing new parameter values to assign to the parameterized gates.
81
+
82
+ Raises:
83
+ ParametersNotEqualError: If the number of provided values does not match the expected number of parameters.
84
+ """
85
+ if len(values) != self.nparameters:
86
+ raise ParametersNotEqualError
87
+ k = 0
88
+ for i, gate in enumerate(self._parameterized_gates):
89
+ gate.set_parameter_values(values[i + k : i + k + gate.nparameters])
90
+ k += gate.nparameters - 1
91
+
92
+ def add(self, gate: Gate) -> None:
93
+ """
94
+ Add a quantum gate to the circuit.
95
+
96
+ Args:
97
+ gate (Gate): The quantum gate to add to the circuit.
98
+
99
+ Raises:
100
+ QubitOutOfRangeError: If any qubit index used by the gate is not within the circuit's qubit range.
101
+ """
102
+ if any(qubit >= self.nqubits for qubit in gate.qubits):
103
+ raise QubitOutOfRangeError
104
+ if gate.is_parameterized:
105
+ self._parameterized_gates.append(gate)
106
+ self._gates.append(gate)
@@ -0,0 +1,20 @@
1
+ # Copyright 2025 Qilimanjaro Quantum Tech
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ from qilisdk.common.algorithm import Algorithm
15
+
16
+
17
+ class DigitalAlgorithm(Algorithm):
18
+ """
19
+ Abstract base class for digital quantum algorithms.
20
+ """
@@ -0,0 +1,90 @@
1
+ # Copyright 2025 Qilimanjaro Quantum Tech
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ from abc import ABC, abstractmethod
15
+ from enum import Enum
16
+
17
+ from qilisdk.digital.circuit import Circuit
18
+ from qilisdk.digital.digital_result import DigitalResult
19
+
20
+
21
+ class DigitalSimulationMethod(str, Enum):
22
+ """
23
+ Enumeration of available simulation methods for the CUDA backend.
24
+ """
25
+
26
+ STATE_VECTOR = "state_vector"
27
+ TENSOR_NETWORK = "tensor_network"
28
+ MATRIX_PRODUCT_STATE = "matrix_product_state"
29
+
30
+
31
+ class DigitalBackend(ABC):
32
+ """
33
+ Abstract base class for digital quantum circuit backends.
34
+
35
+ This abstract class defines the interface for a digital backend capable of executing a
36
+ quantum circuit. Subclasses must implement the execute method to run the circuit with a
37
+ specified number of measurement shots and return a DigitalResult encapsulating the measurement
38
+ outcomes.
39
+ """
40
+
41
+ def __init__(
42
+ self, digital_simulation_method: DigitalSimulationMethod = DigitalSimulationMethod.STATE_VECTOR
43
+ ) -> None:
44
+ """
45
+ Initialize the DigitalBackend.
46
+
47
+ Args:
48
+ simulation_method (DigitalSimulationMethod, optional): The simulation method to use.
49
+ Options include STATE_VECTOR, TENSOR_NETWORK, or MATRIX_PRODUCT_STATE.
50
+ Defaults to STATE_VECTOR.
51
+ """
52
+ self._digital_simulation_method = digital_simulation_method
53
+
54
+ @property
55
+ def digital_simulation_method(self) -> DigitalSimulationMethod:
56
+ """
57
+ Get the simulation method currently configured for the backend.
58
+
59
+ Returns:
60
+ SimulationMethod: The simulation method to be used for circuit execution.
61
+ """
62
+ return self._digital_simulation_method
63
+
64
+ @digital_simulation_method.setter
65
+ def digital_simulation_method(self, value: DigitalSimulationMethod) -> None:
66
+ """
67
+ Set the simulation method for the backend.
68
+
69
+ Args:
70
+ value (SimulationMethod): The simulation method to set. Options include
71
+ STATE_VECTOR, TENSOR_NETWORK, or MATRIX_PRODUCT_STATE.
72
+ """
73
+ self._digital_simulation_method = value
74
+
75
+ @abstractmethod
76
+ def execute(self, circuit: Circuit, nshots: int = 1000) -> DigitalResult:
77
+ """
78
+ Execute the provided quantum circuit and return the measurement results.
79
+
80
+ This method should run the given circuit for the specified number of measurement shots and
81
+ produce a DigitalResult instance containing the raw measurement samples and any computed
82
+ probabilities.
83
+
84
+ Args:
85
+ circuit (Circuit): The quantum circuit to be executed.
86
+ nshots (int, optional): The number of measurement shots to perform. Defaults to 1000.
87
+
88
+ Returns:
89
+ DigitalResult: The result of executing the circuit, including measurement samples and probabilities.
90
+ """
@@ -0,0 +1,145 @@
1
+ # Copyright 2025 Qilimanjaro Quantum Tech
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ import heapq
15
+ import operator
16
+ from pprint import pformat
17
+
18
+ from qilisdk.common import Result
19
+ from qilisdk.yaml import yaml
20
+
21
+
22
+ @yaml.register_class
23
+ class DigitalResult(Result):
24
+ """
25
+ Class representing the result of a quantum circuit measurement.
26
+
27
+ DigitalResult encapsulates the outcome of a digital measurement performed on a quantum circuit.
28
+ It includes the total number of measurement shots, the measurement samples and measurement probabilities.
29
+
30
+ Attributes:
31
+ nshots (int): The number of measurement shots performed in the experiment.
32
+ nqubits (int): The number of qubits measured.
33
+ samples (dict[str, int]): A dictionary where keys are bitstrings representing measurement outcomes and values are the number of times each outcome was observed.
34
+ """
35
+
36
+ def __init__(self, nshots: int, samples: dict[str, int]) -> None:
37
+ """
38
+ Initializes a DigitalResult instance.
39
+
40
+ Args:
41
+ nshots (int): The total number of measurement shots performed.
42
+ samples (dict[str, int]): A dictionary mapping bitstring outcomes to their occurrence counts.
43
+ All keys (bitstrings) must have the same length, which determines the number of qubits.
44
+
45
+ Raises:
46
+ ValueError: If the samples dictionary is empty or if not all bitstring keys have the same length.
47
+ """
48
+ self._nshots = nshots
49
+ self._samples = samples
50
+
51
+ # Ensure samples is not empty and is correct.
52
+ if not samples:
53
+ raise ValueError("The samples dictionary is empty.")
54
+ bitstrings = list(samples.keys())
55
+ nqubits = len(bitstrings[0])
56
+ if not all(len(bitstring) == nqubits for bitstring in bitstrings):
57
+ raise ValueError("Not all bitstring keys have the same length.")
58
+
59
+ # Assign nqubits to attribute
60
+ self._nqubits = nqubits
61
+
62
+ # Calculate probabilities
63
+ self._probabilities = {
64
+ bitstring: counts / self._nshots if self._nshots > 0 else 0.0 for bitstring, counts in self._samples.items()
65
+ }
66
+
67
+ @property
68
+ def nshots(self) -> int:
69
+ """
70
+ Gets the number of measurement shots.
71
+
72
+ Returns:
73
+ int: The total number of measurement shots performed.
74
+ """
75
+ return self._nshots
76
+
77
+ @property
78
+ def nqubits(self) -> int:
79
+ """
80
+ Gets the number of qubits involved in the measurement.
81
+
82
+ Returns:
83
+ int: The number of qubits measured.
84
+ """
85
+ return self._nqubits
86
+
87
+ @property
88
+ def samples(self) -> dict[str, int]:
89
+ """
90
+ Gets the raw measurement samples.
91
+
92
+ Returns:
93
+ dict[str, int]: A dictionary where keys are bitstrings representing measurement outcomes
94
+ and values are the number of times each outcome was observed.
95
+ """
96
+ return dict(self._samples)
97
+
98
+ @property
99
+ def probabilities(self) -> dict[str, float]:
100
+ """
101
+ Gets the probabilities for each measurement outcome.
102
+
103
+ Returns:
104
+ dict[str, float]: A dictionary mapping each bitstring outcome to its corresponding probability.
105
+ """
106
+ return dict(self._probabilities)
107
+
108
+ def get_probability(self, bitstring: str) -> float:
109
+ """
110
+ Computes the probability of a specific measurement outcome.
111
+
112
+ Args:
113
+ bitstring (str): The bitstring representing the measurement outcome of interest.
114
+
115
+ Returns:
116
+ float: The probability of the specified bitstring occurring.
117
+ """
118
+ return self._probabilities.get(bitstring, 0.0)
119
+
120
+ def get_probabilities(self, n: int | None = None) -> list[tuple[str, float]]:
121
+ """
122
+ Returns the n most probable bitstrings along with their probabilities.
123
+
124
+ Parameters:
125
+ n (int): The number of most probable bitstrings to return.
126
+
127
+ Returns:
128
+ list[tuple[str, float]]: A list of tuples (bitstring, probability) sorted in descending order by probability.
129
+ """
130
+ if n is None:
131
+ n = len(self._probabilities)
132
+ return heapq.nlargest(n, self._probabilities.items(), key=operator.itemgetter(1))
133
+
134
+ def __repr__(self) -> str:
135
+ """
136
+ Returns a string representation of the DigitalResult instance for debugging purposes.
137
+
138
+ The representation includes the class name, the number of measurement shots, and a formatted
139
+ display of the measurement samples.
140
+
141
+ Returns:
142
+ str: A string representation of the DigitalResult instance for debugging.
143
+ """
144
+ class_name = self.__class__.__name__
145
+ return f"{class_name}(\n nshots={self.nshots},\n samples={pformat(self.samples)}\n)"
@@ -0,0 +1,31 @@
1
+ # Copyright 2025 Qilimanjaro Quantum Tech
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+
16
+ class QubitOutOfRangeError(Exception): ...
17
+
18
+
19
+ class GateHasNoMatrixError(Exception): ...
20
+
21
+
22
+ class GateNotParameterizedError(Exception): ...
23
+
24
+
25
+ class ParametersNotEqualError(Exception): ...
26
+
27
+
28
+ class InvalidParameterNameError(Exception): ...
29
+
30
+
31
+ class UnsupportedGateError(Exception): ...