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…

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

>>> m1 = np.array([[1,2j,3j],[-2j,4,5j],[-3j,-5j,6]])
>>> is_hermitian(m1)
True
>>> m2 = np.diag([1,2,3,4])
>>> is_hermitian(m2)
True
>>> m3 = np.array([[1,2,3],[2,4,5],[3,5,6]])
>>> is_hermitian(m3)
True
>>> m4 = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> is_hermitian(m4)
False
>>> x = symbols("x", real=True)
>>> m5 = np.diag([1,x])
>>> is_hermitian(m5)
True
>>> m6 = np.array([[1,x],[-x,2]])
>>> is_hermitian(m6)
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

>>> a = np.array([[1,1],[1,-1]])
>>> is_unitary(a)
False
>>> is_unitary(a/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 (ndarray[Any, dtype[complex64]]) – The vector to be normalized.

Returns

The normalized vector.

Return type

ndarray[Any, dtype[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)[source]

Generate a random Clifford matrix.

Parameters
  • size – Size (number of columns) of the square matrix to generate.

  • nb_qubits (int) –

Returns

A random Clifford matrix.

Return type

ndarray[Any, dtype[complex64]]

Examples

>>> rand_clifford_matrix(2) 
array([[ 0.5+0.j, -0.5+0.j,  0.5+0.j, -0.5+0.j],
       [-0.5+0.j,  0.5+0.j,  0.5+0.j, -0.5+0.j],
       [ 0.5+0.j,  0.5+0.j,  0.5+0.j,  0.5+0.j],
       [-0.5+0.j, -0.5+0.j,  0.5+0.j,  0.5+0.j]])
rand_hermitian_matrix(size)[source]

Generate a random Hermitian matrix.

Parameters

size (int) – Size (number of columns) of the square matrix to generate.

Returns

A random Hermitian Matrix.

Return type

ndarray[Any, dtype[complex64]]

Example

>>> rand_hermitian_matrix(2) 
array([[1.4488624 +0.j, 0.20804943+0.j],
       [0.20804943+0.j, 0.7826408 +0.j]], dtype=complex64)
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 control the random generation of the matrix.

Returns

A random orthogonal matrix.

Return type

ndarray[Any, dtype[complex64]]

Examples

>>> rand_orthogonal_matrix(3) 
array([[ 0.94569439,  0.2903415 ,  0.14616405],
       [-0.32503798,  0.83976928,  0.43489984],
       [ 0.0035254 , -0.45879121,  0.88853711]])
>>> rand_orthogonal_matrix(3, seed=42)
array([[ 0.21667149,  0.1867762 ,  0.95821089],
       [ 0.9608116 ,  0.13303749, -0.24319148],
       [-0.17290035,  0.9733528 , -0.15063131]])
rand_product_local_unitaries(nb_qubits)[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.

Returns

A tensor product of random unitary matrices.

Return type

ndarray[Any, dtype[complex64]]

Example

>>> rand_product_local_unitaries(2) 
array([[-0.39648015+0.j        ,  0.49842218-0.16609181j,
           0.39826454-0.21692223j, -0.40979321+0.43953607j],
       [-0.49842218+0.16609181j,  0.14052896-0.37073997j,
           0.40979321-0.43953607j,  0.06167784+0.44929471j],
       [-0.39826454+0.21692223j,  0.40979321-0.43953607j,
           0.16112375-0.36226461j, -0.05079312+0.52290651j],
       [-0.40979321+0.43953607j, -0.06167784-0.44929471j,
           0.05079312-0.52290651j,  0.28163685+0.27906487j]])
rand_unitary_2x2_matrix()[source]

Generate a random one-qubit unitary matrix.

Parameters

size – Size (number of columns) of the square matrix to generate.

Returns

A random Clifford matrix.

Return type

ndarray[Any, dtype[complex64]]

Examples

>>> rand_unitary_2x2_matrix() 
array([[ 0.86889957+0.j        ,  0.44138577+0.22403602j],
       [-0.44138577-0.22403602j, -0.72981565-0.47154594j]])
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

Each of the members of the eum will have the message attribute.

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 and property decorators.

Parameters

func (Callable[..., Any]) –

clean_array(array)[source]

Cleans and formats elements of an array. This function rounds the real parts of complex numbers in the array to 7 decimal places and formats them as integers if they are whole numbers. It returns a string representation of the cleaned array without parentheses.

Parameters

array (list[complex] | numpy.ndarray[Any, numpy.dtype[numpy.complex64 | numpy.float32]]) – An array containing numeric elements, possibly including complex numbers.

Returns

A string representation of the cleaned array without parentheses.

Return type

str

Example

>>> clean_array([1.234567895546, 2.3456789645645, 3.45678945645])
'[1.2345679, 2.345679, 3.4567895]'
>>> clean_array([1+2j, 3+4j, 5+6j])
'[1+2j, 3+4j, 5+6j]'
>>> clean_array([1+0j, 0+0j, 5.])
'[1, 0, 5]'
>>> clean_array([1.0, 2.0, 3.0])
'[1, 2, 3]'
clean_matrix(matrix)[source]

Cleans and formats elements of a matrix. This function cleans and formats the elements of a matrix. It rounds the real parts of complex numbers in the matrix to 7 decimal 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.

Returns

A string representation of the cleaned matrix without parentheses.

Return type

str

Examples

>>> print(clean_matrix([[1.234567895546, 2.3456789645645, 3.45678945645],
...               [1+0j, 0+0j, 5.],
...               [1.0, 2.0, 3.0]]))
[[1.2345679, 2.345679, 3.4567895],
 [1, 0, 5],
 [1, 2, 3]]
find(iterable, oracle)[source]

Finds 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 first element in the iterable that satisfies the oracle.

Raises

ValueError – If no element in the iterable 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
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]

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.

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 to numpy as objects)

alias of Union[ndarray[Any, dtype[complex64]], ndarray[Any, dtype[object_]]]

OneOrMany

Type alias for single elements of type T, or sequences of such elements.

alias of Union[T, Sequence[T]]

T

A generic type.

alias of TypeVar(‘T’)

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 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 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.

exception ResultAttributeError[source]

Bases: AttributeError

Raised when one tries to access the attribute of the result that is incoherent with the associated job.

exception UnsupportedBraketFeaturesWarning[source]

Bases: UserWarning

Warning for potential compatibility issues with Braket.

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)[source]

Bases: object

Represents a node in a decision tree corresponding to a question.

Parameters
answers: list[mpqp.tools.choice_tree.AnswerNode]

List of possible answers to this question.

label: str

The label or text associated with the question.

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)