Tools
Some additional tools are provided with our library. Even though most of them are geared at internal usage, they are all presented here. Amongst them, the ones most probable of being of use for you are in the Useful Maths Operations section, presenting mathematical tools for linear algebra, functions generalized to more data types, etc…
Useful Maths Operations
from mpqp.tools.maths import *
Mathematical tools for linear algebra, functions generalized to more data types, etc…
- closest_unitary(matrix)[source]
Calculate the unitary matrix that is closest with respect to the operator norm distance to the general matrix in parameter.
- Parameters
matrix (Matrix) – Matrix for which we want to determine the closest unitary matrix.
- Returns
The closest unitary matrix.
Example
>>> is_unitary(np.array([[1, 2], [3, 4]])) False >>> u = closest_unitary(np.array([[1, 2], [3, 4]])) >>> u array([[-0.51449576, 0.85749293], [ 0.85749293, 0.51449576]]) >>> is_unitary(u) True
- cos(angle)[source]
Generalization of the cosine function, to take as input either
sympy
’s expressions or floating numbers.- Parameters
angle (Expr | Real) – The angle considered.
- Returns
Cosine of the given
angle
.- Return type
sp.Expr | float
- exp(angle)[source]
Generalization of the exponential function, to take as input either
sympy
’s expressions or floating numbers.- Parameters
angle (Expr | Complex) – The angle considered.
- Returns
Exponential of the given
angle
.- Return type
sp.Expr | complex
- is_hermitian(matrix)[source]
Checks whether the matrix in parameter is hermitian.
- Parameters
matrix (Matrix) – matrix for which we want to know if it is hermitian.
- Returns
True
if the matrix in parameter is Hermitian.- Return type
bool
Examples
>>> is_hermitian(np.array([[1,2j,3j],[-2j,4,5j],[-3j,-5j,6]])) True >>> is_hermitian(np.diag([1,2,3,4])) True >>> m3 = np.array([[1,2,3],[2,4,5],[3,5,6]]) >>> is_hermitian(np.array([[1,2,3],[2,4,5],[3,5,6]])) True >>> m4 = np.array([[1,2,3],[4,5,6],[7,8,9]]) >>> is_hermitian(np.array([[1,2,3],[4,5,6],[7,8,9]])) False >>> x = symbols("x", real=True) >>> is_hermitian(np.diag([1,x])) True >>> is_hermitian(np.array([[1,x],[-x,2]])) False
- is_power_of_two(n)[source]
Checks if the integer in parameter is a (positive) power of two.
- Parameters
n (int) – Integer for which we want to check if it is a power of two.
- Returns
True if the integer in parameter is a power of two.
Example
>>> is_power_of_two(4) True >>> is_power_of_two(6) False
- is_unitary(matrix)[source]
Checks whether the matrix in parameter is unitary.
- Parameters
matrix (Matrix) – Matrix for which we want to know if it is unitary.
- Returns
True
if the matrix in parameter is Unitary.- Return type
bool
Example
>>> is_unitary(np.array([[1,1],[1,-1]])) False >>> is_unitary(np.array([[1,1],[1,-1]])/np.sqrt(2)) True
- matrix_eq(lhs, rhs, atol=1e-08, rtol=1e-05)[source]
Checks whether two matrix (including vectors) are element-wise equal, within a tolerance.
For respectively each elements \(a\) and \(b\) of both inputs, we check this specific condition: \(|a - b| \leq (atol + rtol * |b|)\).
- Parameters
lhs (Matrix) – Left-hand side matrix of the equality.
rhs (Matrix) – Right-hand side matrix of the equality.
atol (float) –
rtol (float) –
- Returns
True
if the two matrix are equal (according to the definition above).- Return type
bool
- normalize(v)[source]
Normalizes an array representing the amplitudes of the state.
- Parameters
v (npt.NDArray[np.complex64]) – The vector to be normalized.
- Returns
The normalized vector.
- Return type
npt.NDArray[np.complex64]
Examples
>>> vector = np.array([1,0,0,1]) >>> normalize(vector) array([0.70710678, 0. , 0. , 0.70710678]) >>> vector = np.array([0,0,0,0]) >>> normalize(vector) array([0, 0, 0, 0])
- rand_clifford_matrix(nb_qubits, seed=None)[source]
Generate a random Clifford matrix.
- Parameters
size – Size (number of columns) of the square matrix to generate.
seed (Optional[int]) – Seed used to initialize the random number generation.
nb_qubits (int) –
- Returns
A random Clifford matrix.
- Return type
npt.NDArray[np.complex64]
Examples
>>> pprint(rand_clifford_matrix(2)) [[-0.5 , 0.5 , 0.5j , -0.5j], [-0.5j, -0.5j, 0.5 , 0.5 ], [-0.5j, -0.5j, -0.5 , -0.5 ], [-0.5 , 0.5 , -0.5j, 0.5j ]]
>>> pprint(rand_clifford_matrix(2, seed=123)) [[0.70711j, 0 , -0.70711j, 0 ], [0 , -0.70711j, 0 , -0.70711j], [0 , 0.70711j , 0 , -0.70711j], [0.70711j, 0 , 0.70711j , 0 ]]
- rand_hermitian_matrix(size, seed=None)[source]
Generate a random Hermitian matrix.
- Parameters
size (int) – Size (number of columns) of the square matrix to generate.
seed (Optional[int]) – Seed used to initialize the random number generation.
- Returns
A random Hermitian Matrix.
- Return type
npt.NDArray[np.complex64]
Example
>>> pprint(rand_hermitian_matrix(2)) [[1.2917 , 0.64402], [0.64402, 1.10203]]
>>> pprint(rand_hermitian_matrix(2, seed=123)) [[1.3647 , 0.27418], [0.27418, 0.36874]]
- rand_orthogonal_matrix(size, seed=None)[source]
Generate a random orthogonal matrix optionally with a given seed.
- Parameters
size (int) – Size (number of columns) of the square matrix to generate.
seed (Optional[int]) – Seed used to initialize the random number generation.
- Returns
A random orthogonal matrix.
- Return type
npt.NDArray[np.complex64]
Examples
>>> pprint(rand_orthogonal_matrix(3)) [[0.70957 , 0.13959, 0.69067], [0.61432 , 0.35754, -0.7034], [-0.34513, 0.92341, 0.16795]]
>>> pprint(rand_orthogonal_matrix(3, seed=123)) [[0.75286 , -0.65782, 0.02175], [-0.22778, -0.22939, 0.94631], [0.61751 , 0.71739 , 0.32254]]
- rand_product_local_unitaries(nb_qubits, seed=None)[source]
Generate a pseudo random matrix, resulting from a tensor product of random unitary matrices.
- Parameters
nb_qubits (int) – Number of qubits on which the product of unitaries will act.
seed (Optional[int]) – Seed used to initialize the random number generation.
- Returns
A tensor product of random unitary matrices.
- Return type
npt.NDArray[np.complex64]
Example
>>> pprint(rand_product_local_unitaries(2)) [[0.07059 , 0.43591+0.02564j , 0.09107+0.1104j , 0.52233+0.71486j ], [-0.43591-0.02564j, -0.06-0.03719j , -0.52233-0.71486j, -0.01924-0.14182j], [-0.09107-0.1104j , -0.52233-0.71486j, -0.04361-0.05551j, -0.24913-0.35863j], [0.52233+0.71486j , 0.01924+0.14182j , 0.24913+0.35863j , 0.00782+0.07015j ]]
>>> pprint(rand_product_local_unitaries(2, seed=123)) [[-0.45364 , 0.11284-0.27441j , -0.13022-0.69112j, 0.45045+0.09315j ], [-0.11284+0.27441j, -0.45235+0.03417j, -0.45045-0.09315j, -0.18191-0.67934j], [0.13022+0.69112j , -0.45045-0.09315j, 0.06866-0.44841j , 0.25417+0.15308j ], [0.45045+0.09315j , 0.18191+0.67934j , -0.25417-0.15308j, 0.03469-0.45231j ]]
- rand_unitary_2x2_matrix(seed=None)[source]
Generate a random one-qubit unitary matrix.
- Parameters
size – Size (number of columns) of the square matrix to generate.
seed (Optional[Union[int, np.random.Generator]]) – Used for the random number generation. If unspecified, a new generator will be used. If a
Generator
is provided, it will be used to generate any random number needed. Finally if anint
is provided, it will be used to initialize a new generator.
- Returns
A random Clifford matrix.
- Return type
npt.NDArray[np.complex64]
Examples
>>> pprint(rand_unitary_2x2_matrix()) [[-0.44234 , -0.57071-0.69183j], [0.57071+0.69183j, 0.27325+0.34784j ]]
>>> pprint(rand_unitary_2x2_matrix(seed=123)) [[-0.54205 , -0.1556-0.82582j], [0.1556+0.82582j, 0.08204-0.53581j]]
- sin(angle)[source]
Generalization of the sine function, to take as input either
sympy
’s expressions or floating numbers.- Parameters
angle (Expr | Real) – The angle considered.
- Returns
Sine of the given
angle
.- Return type
sp.Expr | float
- atol = 1e-08
The absolute tolerance parameter.
- rtol = 1e-05
The relative tolerance parameter.
Generics
from mpqp.tools.generics import *
This module contains a collection of generic types and functions needed across the library.
Type aliases Matrix
, OneOrMany
and ArbitraryNestedSequence
are used across the library. In particular, ArbitraryNestedSequence
is
used in cases the nesting of the sequence is unknown; and in these cases you
might want to flatten the list using flatten()
.
On occasion, there is also a need to “flatten” the string representation of an
object i.e. to display it on one line. In this case one_line_repr()
is
your friend.
Lastly, we find the default list search mechanism in python a bit too
restrictive. find()
allow us a much more versatile search using an
oracle
.
- class MessageEnum(value=<no_arg>, names=None, module=None, qualname=None, type=None, start=1, boundary=None)[source]
Bases:
Enum
Enum subclass allowing you to access the docstring of the members of your enum through the
message
property.Example
>>> class A(MessageEnum): ... '''an enum''' ... VALUE1 = auto() ... '''member VALUE1''' ... VALUE2 = auto() ... '''member VALUE2''' >>> A.VALUE1.message 'member VALUE1'
Warning
This implementation is not very robust, in particular, in case some members are not documented, it will mess things up. In addition, this can only work for code in file, and will not work in the interpreter.
- message: str
This is an attribute for each member of the enum, giving more information about it.
- class SimpleClassReprABC[source]
Bases:
object
This class is the equivalent of ABC (it signifies that it’s subclass isn’t meant to be instantiated directly), but it adds the small feature of setting the
repr
to be the class name, which is for instance useful for gates.
- class SimpleClassReprABCMeta(name, bases, namespace, **kwargs)[source]
Bases:
SimpleClassReprMeta
,ABCMeta
- class SimpleClassReprMeta[source]
Bases:
type
Metaclass used to change the repr of the class (not the instances) to display the name of the class only (instead of the usual <class mpqp.path.ClassName>)
- class classproperty(func)[source]
Bases:
object
Decorator yo unite the
classmethod
andproperty
decorators.- Parameters
func (Callable[..., Any]) –
- find(sequence, oracle)[source]
Finds the first element in the sequence that satisfies the given oracle.
- Parameters
sequence (Sequence[T]) – The sequence to search for the element.
oracle (Callable[[T], bool]) – A callable function that takes an element and returns
True
if the element satisfies the condition.
- Returns
The first element in the sequence that satisfies the oracle.
- Raises
ValueError – If no element in the sequence satisfies the given oracle.
- Return type
T
Example
>>> numbers = [1, 2, 3, 4, 5] >>> is_even = lambda x: x % 2 == 0 >>> find(numbers, is_even) 2
- find_index(iterable, oracle)[source]
Finds the index of the first element in the iterable that satisfies the given oracle.
- Parameters
iterable (Iterable[T]) – The iterable to search for the element.
oracle (Callable[[T], bool]) – A callable function that takes an element and returns
True
if the element satisfies the condition.
- Returns
The index of the first element in the iterable that satisfies the oracle.
- Raises
ValueError – If no element in the iterable satisfies the given oracle.
- Return type
int
Example
>>> numbers = [1, 2, 3, 4, 5] >>> is_even = lambda x: x % 2 == 0 >>> find_index(numbers, is_even) 1
- flatten(lst)[source]
Flattens an arbitrarily nested Sequence.
This is a wrapper around
flatten_generator()
.- Parameters
lst (Union[Sequence[ArbitraryNestedSequence[T]], T]) – The nested sequence, to be flattened.
- Returns
A flattened list containing all elements from the input list.
- Return type
list[~T]
Example
>>> nested_list = [[1, 2, [3, 4]], [5, [6, 7]], 8] >>> flatten(nested_list) [1, 2, 3, 4, 5, 6, 7, 8]
- flatten_generator(lst)[source]
Helper generator function for flattening an arbitrarily nested list.
- Parameters
lst (Union[Sequence[ArbitraryNestedSequence[T]], T]) – The list, or nested list, to be flattened.
- Yields
Elements from the input list in a flattened order.
- Return type
Iterator[T]
- ArbitraryNestedSequence
This type alias allows us to define heterogeneously nested Sequences of
T
.Examples
>>> l: ArbitraryNestedSequence[int] >>> l = [[0,1],0,[[0,2],3]] >>> l = 1 >>> l = [2,1,3]
alias of
Union
[Sequence
[ArbitraryNestedSequence[T]
],T
]
- Matrix
Type alias denoting all the matrices we consider (either matrices of complex or of
sympy
expressions, given tonumpy
as objects)alias of
Union
[ndarray
[Any
,dtype
[complex64
]],ndarray
[Any
,dtype
[object_
]]]
- T
A generic type.
alias of TypeVar(‘T’)
Display helpers
from mpqp.tools.display import *
- clean_1D_array(array, round=5)[source]
Cleans and formats elements of a one dimensional array. This function rounds the parts of the numbers in the array and formats them as integers if appropriate. It returns a string representation of the cleaned array.
- Parameters
array (list[complex] | npt.NDArray[np.complex64 | np.float32]) – An array containing numeric elements.
round (int) – precision to round the numbers to.
- Returns
A string representation of the cleaned array.
- Return type
str
Example
>>> clean_1D_array([1.234567895546, 2.3456789645645, 3.45678945645]) '[1.23457, 2.34568, 3.45679]' >>> clean_1D_array([1+2j, 3+4j, 5+6j]) '[1+2j, 3+4j, 5+6j]' >>> clean_1D_array([1+0j, 0.5+0j, 5.+1j]) '[1, 0.5, 5+1j]' >>> clean_1D_array([1.0, 2.1, 3.0]) '[1, 2.1, 3]' >>> clean_1D_array([1+0j, 0+0j, 5.]) '[1, 0, 5]' >>> clean_1D_array([1.0, 2.0, 3.0]) '[1, 2, 3]' >>> clean_1D_array([-0.01e-09+9.82811211e-01j, 1.90112689e-01+5.22320655e-09j, ... 2.91896816e-09-2.15963155e-09j, -4.17753839e-09-5.64638430e-09j, ... 9.44235988e-08-8.58300965e-01j, -5.42123454e-08+2.07957438e-07j, ... 5.13144658e-01+2.91786504e-08j, -0000000.175980538-1.44108434e-07j]) '[0.98281j, 0.19011, 0, 0, -0.8583j, 0, 0.51314, -0.17598]' >>> clean_1D_array([-0.01e-09+9.82811211e-01j, 1.90112689e-01+5.22320655e-09j, ... 2.91896816e-09-2.15963155e-09j, -4.17753839e-09-5.64638430e-09j, ... 9.44235988e-08-8.58300965e-01j, -5.42123454e-08+2.07957438e-07j, ... 5.13144658e-01+2.91786504e-08j, -0000000.175980538-1.44108434e-07j], round=7) '[0.9828112j, 0.1901127, 0, 0, 1e-07-0.858301j, -1e-07+2e-07j, 0.5131446, -0.1759805-1e-07j]'
- clean_matrix(matrix, round=5, align=True)[source]
Cleans and formats elements of a 2D matrix. This function rounds the parts of the numbers in the matrix and formats them as integers if appropriate. It returns a string representation of the cleaned matrix.
- Parameters
matrix (Matrix) – An 2d array containing numeric elements.
round (int) – The number of decimal places to round the real and imaginary parts.
align (bool) – Whether to align the elements for a cleaner output.
- Returns
A string representation of the cleaned matrix.
Examples
>>> print(clean_matrix(np.array([[1.234567895546, 2.3456789645645, 3.45678945645], ... [1+5j, 0+1j, 5.], ... [1.223123425+0.95113462364j, 2.0, 3.0]]))) [[1.23457 , 2.34568, 3.45679], [1+5j , 1j , 5 ], [1.22312+0.95113j, 2 , 3 ]]
- clean_number_repr(number, round=7)[source]
Cleans and formats a number. This function rounds the parts of complex numbers and formats them as integers if appropriate. It returns a string representation of the number.
- Parameters
number (Union[complex, complex64]) – The number to be formatted
round (int) –
- Returns
A string representation of the number.
Example
>>> clean_number_repr(1.234567895546) '1.2345679' >>> clean_number_repr(1.0+2.0j) '1+2j' >>> clean_number_repr(1+0j) '1' >>> clean_number_repr(0.0 + 1.0j) '1j'
- format_element(element, round=5)[source]
Formats a numeric or symbolic element for cleaner representation. Rounds the real and imaginary parts of a number to a specified number of decimal places, formats whole numbers as integers, and properly handles symbolic expressions by simplifying them. It produces a string representation of the element, with ‘j’ notation for complex numbers and a simplified form for symbolic expressions.
- Parameters
element (Union[int, float, complex | Expr]) – The element to format, which can be an integer, float, complex number, or symbolic expression.
round (int) – The number of decimal places to round to for real and imaginary parts.
- Returns
A string representation of the formatted element.
- Return type
str
Example
>>> format_element(3.456789, round=4) '3.4568' >>> format_element(1+2j, round=2) '1+2j' >>> format_element(3+0j) '3' >>> from sympy import symbols, Expr >>> x = symbols('x') >>> format_element(Expr(x + x)) '2*x'
- one_lined_repr(obj)[source]
One-liner returning a representation of the given object by removing extra whitespace.
- Parameters
obj (object) – The object for which a representation is desired.
- pprint(matrix, round=5, align=True)[source]
Print a cleans and formats elements of a matrix. It rounds the real parts of complex numbers in the matrix places and formats them as integers if they are whole numbers. It returns a string representation of the cleaned matrix without parentheses.
- Parameters
matrix (Matrix) – A matrix containing numeric elements, possibly including complex numbers.
round (int) – The number of decimal places to round the real and imaginary parts.
align (bool) – Whether to align the elements for a cleaner output.
Example
>>> pprint(np.array([[1.234567895546, 2.3456789645645, 3.45678945645], ... [1+5j, 0+1j, 5.], ... [1.223123425+0.95113462364j, 2.0, 3.0]])) [[1.23457 , 2.34568, 3.45679], [1+5j , 1j , 5 ], [1.22312+0.95113j, 2 , 3 ]]
- state_vector_ket_shape(sv)[source]
Formats a state vector into its ket format.
- Parameters
sv (npt.NDArray[np.complex64]) –
- Return type
str
- with_sign(val)[source]
Sometimes, we want values under a specific format, in particular
<sign> <value>
. Where value is as simple as possible (e.g. no period or no imaginary part if there is no need).- Parameters
val (Union[complex64, complex128]) – The value to be formatted.
- Returns
The formatted value
- Return type
str
Errors
from mpqp.tools.errors import *
You will find here the custom exceptions we created in order to provide clearer errors. When relevant, we also append the trace of the error raised by a provider’s SDK.
- exception AWSBraketRemoteExecutionError[source]
Bases:
RemoteExecutionError
Raised when an error occurred during the remote execution process of job(s) on the remote Amazon Braket.
- exception AdditionalGateNoiseWarning[source]
Bases:
UserWarning
Warning for additional noise on native gate used in the decomposition of noisy gate.
- exception DeviceJobIncompatibleError[source]
Bases:
ValueError
Raised when one tries to run a job with a JobType that is not suitable for the selected device (for example SAMPLE job on a statevector simulator).
- exception IBMRemoteExecutionError[source]
Bases:
RemoteExecutionError
Raised when an error occurred during the remote execution process of job(s) on an IBM device.
- exception InstructionParsingError[source]
Bases:
ValueError
Raised when an QASM instruction encountered by the parser is malformed.
- exception NonReversibleWarning[source]
Bases:
UserWarning
Warning for nonreversible instruction used in inverse function.
- exception NumberQubitsError[source]
Bases:
ValueError
Raised when the number of qubits defining an instruction, a gate, or a measurement, is not coherent with the related objects (circuit, matrix, observable, etc…).
- exception NumberQubitsWarning[source]
Bases:
UserWarning
Raised when the number of qubits defining an instruction, a gate, or a measurement, is not coherent with the related objects (circuit, matrix, observable, etc…).
- exception OpenQASMTranslationWarning[source]
Bases:
UserWarning
Warning for potential translation error when exporting to OpenQASM.
- exception QLMRemoteExecutionError[source]
Bases:
RemoteExecutionError
Raised when an error occurred during the remote execution process of job(s) on the remote QLM.
- exception RemoteExecutionError[source]
Bases:
ConnectionError
Raised when an error occurred during a remote connection, submission or execution.
Circuit tricks
from mpqp.tools.circuit import *
- compute_expected_matrix(qcircuit)[source]
Computes the expected matrix resulting from applying single-qubit gates in reverse order on a quantum circuit.
- Parameters
qcircuit (QCircuit) – The quantum circuit object containing instructions.
- Returns
Expected matrix resulting from applying the gates.
- Raises
ValueError – If any gate in the circuit is not a SingleQubitGate.
- random_circuit(gate_classes=None, nb_qubits=5, nb_gates=None, seed=None)[source]
This function creates a QCircuit with a specified number of qubits and gates. The gates are chosen randomly from the provided list of native gate classes.
- Parameters
nb_qubits (int) – Number of qubits in the circuit.
gate_classes (Optional[Sequence[type[Gate]]]) – List of native gate classes to use in the circuit.
nb_gates (Optional[int]) – Number of gates to add to the circuit.
seed (Optional[int]) – Seed used to initialize the random number generation.
- Returns
A quantum circuit with the specified number of qubits and randomly chosen gates.
- Raises
ValueError – If the number of qubits is too low for the specified gates.
Examples
>>> print(random_circuit([U, TOF], 3)) ┌───┐┌───┐ ┌───┐ ┌───┐┌───┐ q_0: ┤ X ├┤ X ├──■──┤ X ├────────────────────────────┤ X ├┤ X ├ └─┬─┘└─┬─┘┌─┴─┐└─┬─┘ └─┬─┘└─┬─┘ q_1: ──■────■──┤ X ├──■────────────────────────────────■────■── │ │ └─┬─┘ │ ┌──────────────────────────┐ │ │ q_2: ──■────■────■────■──┤ U(0.31076,5.5951,6.2613) ├──■────■── └──────────────────────────┘
>>> print(random_circuit([U, TOF], 3, seed=123)) ┌───┐ ┌───┐ q_0: ──■──┤ X ├───────────────────────────┤ X ├ ┌─┴─┐└─┬─┘┌─────────────────────────┐└─┬─┘ q_1: ┤ X ├──■──┤ U(5.1025,5.8015,1.7378) ├──■── └─┬─┘ │ ├─────────────────────────┤ │ q_2: ──■────■──┤ U(5.5914,3.2231,1.5392) ├──■── └─────────────────────────┘
- random_gate(gate_classes=None, nb_qubits=5, seed=None)[source]
This function creates a gate with a specified number of qubits. The gate are chosen randomly from the provided list of native gate classes.
- Parameters
nb_qubits (int) – Number of qubits in the circuit.
gate_classes (Optional[Sequence[type[Gate]]]) – List of native gate classes to use in the circuit.
seed (Optional[Union[int, Generator]]) –
- Returns
A quantum circuit with the specified number of qubits and randomly chosen gates.
- Raises
ValueError – If the number of qubits is too low for the specified gates.
- Return type
Examples
>>> random_gate([U, TOF], 3) U(2.067365317109373, 0.18652872274018245, 0.443968374745352, 0) >>> random_gate(nb_qubits=4) SWAP(3, 1)
- random_noise(noise_model=None, seed=None)[source]
This function creates a noise model. The noise are chosen randomly from the provided list of noise model.
- Parameters
noise_model (Optional[Sequence[type[mpqp.noise.noise_model.NoiseModel]]]) – List of noise model.
seed (Optional[Union[int, Generator]]) –
- Returns
A quantum circuit with the specified number of qubits and randomly chosen gates.
- Raises
ValueError – If the number of qubits is too low for the specified gates.
- Return type
Examples
>>> random_noise() Depolarizing(0.37785041428875576)
- replace_custom_gate(custom_unitary, nb_qubits)[source]
Decompose and replace the (custom) qiskit unitary given in parameter by a qiskit \(QuantumCircuit\) composed of
U
andCX
gates.Note
When using Qiskit, a global phase is introduced (related to usage of
u
in OpenQASM2). This may be problematic in some cases, so this function also returns the global phase introduced so it can be corrected later on.- Parameters
custom_unitary (CircuitInstruction) – instruction containing the custom unitary operator.
nb_qubits (int) – Number of qubits of the circuit from which the unitary instruction was taken.
- Returns
A circuit containing the decomposition of the unitary in terms of gates
U
andCX
, and the global phase used to correct the statevector if need be.- Return type
tuple[‘QuantumCircuit’, float]
Choice Tree
from mpqp.tools.choice_tree import *
This module provides functionalities for working with decision trees, allowing for seamless navigation and interaction within a tree structure.
You can define a QuestionNode
, containing your question and options.
Each option (AnswerNode
) contains the description of the option
together with optional actions and follow up question.
To run your choice tree, just run run_choice_tree()
on your root question.
- class AnswerNode(label, action, next_question=None)[source]
Bases:
object
Represents a node in a decision tree corresponding to an answer to a question. An answer can lead to an action, or to another question.
- Parameters
label (str) – See attribute description.
action (Callable[[...], tuple[str, Iterable[Any]]]) – See attribute description.
next_question (Optional[QuestionNode]) – See attribute description.
- action: Callable[[...], tuple[str, Iterable[Any]]]
A callable representing an action function linked to an answer. The return value of the action is composed of the text to display after it ran (something like “Success”, “Failure”, or “You’re a wonderful human being”), and the parameters to pass to the next action to be executed. These parameters to be passed between actions are useful to keep memory of the previous actions for instance.
- label: str
The label or text associated with the answer.
- next_question: Optional[QuestionNode] = None
An optional reference to the next question node.
- class QuestionNode(label, answers, leaf_loop_to_here=False)[source]
Bases:
object
Represents a node in a decision tree corresponding to a question.
- Parameters
label (str) – The label or text associated with the question.
answers (list[mpqp.tools.choice_tree.AnswerNode]) – List of possible answers to this question.
leaf_loop_to_here (bool) – If
True
answers without followup questions will loop back to here.
- answers: list[mpqp.tools.choice_tree.AnswerNode]
- label: str
- leaf_loop_to_here: bool = False
- run_choice_tree(question)[source]
Execute the choice tree by starting with the question node in parameter.
- Parameters
question (QuestionNode) – Root question from which the choice tree will start
Example
def tea_picker(*_):
name = input("What's your favorite tea brand?\n\t")
return f"Very good choice, I love {name}!", [name]
choice_tree = QuestionNode(
"Hey, what's your favorite beverage?",
[
AnswerNode(
"Tea",
tea_picker,
QuestionNode(
"Do you want to come at my place to drink some",
[
AnswerNode(
"Yes", lambda n: (f"Cool, let's go for this cup of {n} :D", [])
),
AnswerNode("Can't :(", lambda n: ("No worries, another time!", [])),
],
),
),
AnswerNode(
"Coffee",
lambda: ("I get it, you gotta do what you gotta do to stay awake", []),
QuestionNode(
"And how do you like it?",
[
AnswerNode(
"American style",
lambda: (
"Hydrating is important, but I'm not sure this counts as coffee",
[],
),
),
AnswerNode("Italian", lambda: ("The only right way!", [])),
],
),
),
],
)
assert choice_tree.answers[-1].next_question is not None
choice_tree.answers[-1].next_question.answers[0].next_question = choice_tree
run_choice_tree(choice_tree)
Theoretical simulations
from mpqp.tools.theoretical_simulation import *
This module contains the tools to check if a result obtained by running the circuit on one of our provider’s device produce a result compatible with the theory. (Which could itself be useful to find problems either in our code or in our provider’s code.)
In order to do so, theoretical_probs()
performs a theoretical simulation
of a QCircuit
. The noise models in the circuit will
be taken into account (but not the shot noise).
This theoretical simulation will be compared against the execution on a
AvailableDevice
in exp_id_dist()
. This
comparison is performed using a distance between statistical distribution called
the Jensen-Shannon distance.
If the distance is small enough, validate_noisy_circuit()
will return
True
, meaning that the empirical data is within the expected range.
The size of the trust interval is computed in trust_int()
by computing the
Jensen-Shannon distance between a non noisy circuit and a noisy one. The idea
being that the more noise you have in a circuit, the bigger your trust interval
needs to be (the uncertainty is bigger).
The interval size is not linearly related with this distance so this needs to be
passed in a re-normalizing function before being used. This is the role
dist_alpha_matching()
is playing.
- amplitude(circ)[source]
Computes the theoretical probabilities of a (potentially) noisy circuit execution.
- Parameters
circ (QCircuit) – The circuit to run.
- Returns
The probabilities corresponding to each basis state.
- Return type
ndarray[Any, dtype[complex64]]
- dist_alpha_matching(alpha)[source]
The trust interval is computed from the distance between the circuit without noise and the noisy circuits probability distributions. This interval depends on this distance in a non linear manner. This function gives the relation between the two.
- Parameters
alpha (float) – The distance Jensen-Shannon between the non noisy distribution and the noisy distribution.
- Returns
Diameter of the trust interval for the distance.
- exp_id_dist(circuit, shots=1024, device=AWSDevice.BRAKET_LOCAL_SIMULATOR)[source]
This function computes Jensen-Shannon the distance between the non noisy distribution and the noisy distribution.
- Parameters
circuit (QCircuit) – The circuit.
shots (int) – Number of shots in the basis measurement.
device (AvailableDevice) – The device to be tested.
- Returns
The distance between the non noisy distribution and the noisy distribution.
- exp_id_dist_excess(circuit, shots=1024)[source]
Computes the gap between theory and our noise pipeline for a circuit.
- Parameters
circuit (QCircuit) – The circuit (with potential noises).
shots (int) – Number of shots in the basis measurement.
- Returns
the distance between theory and our results;
and the trust interval.
- Return type
The gap between
- theoretical_probs(circ)[source]
Computes the theoretical probabilities of a (potentially) noisy circuit execution.
- Parameters
circ (QCircuit) – The circuit to run.
- Returns
The probabilities corresponding to each basis state.
- Return type
ndarray[Any, dtype[float32]]
- trust_int(circuit)[source]
Given a circuit, this computes the diameter of the trust interval for the output samples given into consideration the noise in the circuit.
- Parameters
circuit (QCircuit) – The circuit.
- Returns
The size of the trust interval (related to the Jensen-Shannon distance).
- validate_noisy_circuit(circuit, shots=1024, device=AWSDevice.BRAKET_LOCAL_SIMULATOR)[source]
Validates our noise pipeline for a circuit.
- Parameters
circuit (QCircuit) – The circuit (with potential noises).
shots (int) – Number of shots in the basis measurement.
device (AvailableDevice) – The device to be tested.
- Returns
Weather our noise pipeline matches the theory or not.
- Return type
bool