qml.pauli.PauliVSpace¶
- class PauliVSpace(generators, dtype=<class 'float'>, tol=None)[source]¶
Bases:
object
Class representing the linearly independent basis of a vector space.
The main purpose of this class is to store and process
M
, which is a dictionary-of-keys (DOK) style sparse representation of the set of basis vectors. You can think of it as the numpy-equivalent of a PauliSentence: eachPauliWord
(key ofPauliSentence
) represents one row ofM
with the coefficient (value ofPauliSentence
). For example the set of 3 linearly independent generatorsX(0) + X(1), X(0) + X(2), X(0) + 0.5 * Y(0)
can be represented as[ [1, 1, 1], [1, 0, 0], [0, 1, 0], [0, 0, 0.5] ]
where each column represents one sentence, and each row represents the coefficient of the respective word in the sentence. To make sense of this representation one additionally needs to keep track of the mapping between keys and rows. In this case we have
pw_to_idx = { X(0) : 0, X(1) : 1, X(2) : 2, Y(0) : 3 }
where we have set the numbering based on appearance in the list of generators. This mapping is in general not unique.
- Parameters
generators (Iterable[Union[PauliWord, PauliSentence, Operator]]) – Operators that span the vector space.
dtype (type) –
dtype
of the underlying DOK sparse matrixM
. Default isfloat
.tol (float) – Numerical tolerance for the linear independence check. If the norm of the projection of the candidate vector onto \(M^\perp\) is greater than
tol
, then it is deemed to be linearly independent.
Example
Take a linearly dependent set of operators and span the PauliVSpace.
ops = [ X(0) @ X(1) + Y(0) @ Y(1), X(0) @ X(1), Y(0) @ Y(1) ] vspace = PauliVSpace(ops)
It automatically detects that the third operator is linearly dependent on the former two, so it does not add the third operator to the basis.
>>> vspace.basis [1.0 * X(0) @ X(1) + 1.0 * Y(0) @ Y(1), 1.0 * X(0) @ X(1)]
We can also retrospectively add operators.
>>> vspace.add(qml.X(0)) [1.0 * X(0) @ X(1) + 1.0 * Y(0) @ Y(1), 1.0 * X(0) @ X(1), 1.0 * X(0)]
Again, checks of linear independence are always performed. So in the following example no operator is added.
>>> vspace.add(Y(0) @ Y(1)) [1.0 * X(0) @ X(1) + 1.0 * Y(0) @ Y(1), 1.0 * X(0) @ X(1), 1.0 * X(0)]
Attributes
Methods
add
(other[, tol])Adding Pauli sentences if they are linearly independent.
is_independent
(pauli_sentence[, tol])Check if the
pauli_sentence
is linearly independent of the basis ofPauliVSpace
.- add(other, tol=None)[source]¶
Adding Pauli sentences if they are linearly independent.
- Parameters
other (List[
PauliWord
,PauliSentence
,Operator
]) – List of candidate operators to add to thePauliVSpace
, if they are linearly independent.tol (float) – Numerical tolerance for linear independence check. Defaults to
1e-15
.
- Returns
New basis vectors after adding the linearly independent ones from
other
.- Return type
List
Example
We can generate a
PauliVSpace
and add a linearly independent operator to its basis.>>> ops = [X(0), X(1)] >>> vspace = qml.pauli.PauliVSpace(ops) >>> vspace.add(Y(0)) >>> vspace [1.0 * X(0), 1.0 * X(1), 1.0 * Y(0)]
We can add a list of operators at once. Only those that are linearly dependent with the current
PauliVSpace
are added.>>> vspace.add([Z(0), X(0)]) [1.0 * X(0), 1.0 * X(1), 1.0 * Y(0), 1.0 * Z(0)]
- is_independent(pauli_sentence, tol=None)[source]¶
Check if the
pauli_sentence
is linearly independent of the basis ofPauliVSpace
.- Parameters
pauli_sentence (~.PauliSentence) – Candidate Pauli sentence to check against the
PauliVSpace
basis for linear independence.tol (float) – Numerical tolerance for linear independence check. Defaults to
1e-15
.
- Returns
whether
pauli_sentence
was linearly independent- Return type
bool
Example
>>> ops = [X(0), X(1)] >>> vspace = PauliVSpace([op.pauli_rep for op in ops]) >>> vspace.is_independent(X(0).pauli_rep) False >>> vspace.is_independent(Y(0).pauli_rep) True