View source on GitHub |
Represents a multi-qubit pauli operator or pauli observable.
Inherits From: Operation
cirq.PauliString(
*contents,
qubit_pauli_map: Optional[Dict[TKey, 'cirq.Pauli']] = None,
coefficient: 'cirq.TParamValComplex' = 1
)
Used in the notebooks
Used in the tutorials |
---|
cirq.PauliString
represents a multi-qubit pauli operator, i.e.
a tensor product of single qubit (non identity) pauli operations,
each acting on a different qubit. For example,
- X(0) * Y(1) * Z(2): Represents a pauli string which is a tensor product of
cirq.X(q0)
,cirq.Y(q1)
andcirq.Z(q2)
.
If more than one pauli operation acts on the same set of qubits, their composition is
immediately reduced to an equivalent (possibly multi-qubit) Pauli operator. Also, identity
operations are dropped by the PauliString
class. For example:
a, b = cirq.LineQubit.range(2)
print(cirq.X(a) * cirq.Y(b)) # Tensor product of Pauli's acting on different qubits.
X(q(0))*Y(q(1))
print(cirq.X(a) * cirq.Y(a)) # Composition is reduced to an equivalent PauliString.
1j*Z(q(0))
print(cirq.X(a) * cirq.I(b)) # Identity operations are dropped by default.
X(q(0))
print(cirq.PauliString()) # String representation of an "empty" PaulString is "I".
I
cirq.PauliString
is often used to represent:
- Pauli operators: Can be inserted into circuits as multi qubit operations.
- Pauli observables: Can be measured using either
cirq.measure_single_paulistring
/cirq.measure_paulistring_terms
; or using the observable measurement framework incirq.measure_observables
.
PauliStrings can be constructed via various different ways, some examples are given as follows:
a, b, c = cirq.LineQubit.range(3)
print(cirq.PauliString([cirq.X(a), cirq.X(a)]))
I
print(cirq.PauliString(-1, cirq.X(a), cirq.Y(b), cirq.Z(c)))
-X(q(0))*Y(q(1))*Z(q(2))
print(-1 * cirq.X(a) * cirq.Y(b) * cirq.Z(c))
-X(q(0))*Y(q(1))*Z(q(2))
print(cirq.PauliString({a: cirq.X}, [-2, 3, cirq.Y(a)]))
-6j*Z(q(0))
print(cirq.PauliString({a: cirq.I, b: cirq.X}))
X(q(1))
print(cirq.PauliString({a: cirq.Y}, qubit_pauli_map={a: cirq.X}))
1j*Z(q(0))
Note that cirq.PauliString
s are immutable objects. If you need a mutable version
of pauli strings, see cirq.MutablePauliString
.
Raises | |
---|---|
TypeError
|
If the qubit_pauli_map has values that are not Paulis.
|
Attributes | |
---|---|
classical_controls
|
The classical controls gating this operation. |
coefficient
|
A scalar coefficient or symbol. |
gate
|
Returns a cirq.DensePauliString
|
qubits
|
Returns a tuple of qubits on which this pauli string acts. |
tags
|
Returns a tuple of the operation's tags. |
untagged
|
Returns the underlying operation without any tags. |
Methods
after
after(
ops: 'cirq.OP_TREE'
) -> 'cirq.PauliString'
Determines the equivalent pauli string after some operations.
If the PauliString is \(P\) and the Clifford operation is \(C\), then the result is \(C P C^\dagger\).
Args | |
---|---|
ops
|
A stabilizer operation or nested collection of stabilizer operations. |
Returns | |
---|---|
The result of propagating this pauli string from before to after the given operations. |
before
before(
ops: 'cirq.OP_TREE'
) -> 'cirq.PauliString'
Determines the equivalent pauli string before some operations.
If the PauliString is \(P\) and the Clifford operation is \(C\), then the result is \(C^\dagger P C\).
Args | |
---|---|
ops
|
A stabilizer operation or nested collection of stabilizer operations. |
Returns | |
---|---|
The result of propagating this pauli string from after to before the given operations. |
conjugated_by
conjugated_by(
clifford: 'cirq.OP_TREE'
) -> 'PauliString'
Returns the Pauli string conjugated by a clifford operation.
The product-of-Paulis \(P\) conjugated by the Clifford operation \(C\) is
$$
C^\dagger P C
$$
For example, conjugating a +Y operation by an S operation results in a +X operation (as opposed to a -X operation).
In a circuit diagram where P
is a pauli string observable immediately
after a Clifford operation C
, the pauli string P.conjugated_by(C)
is
the equivalent pauli string observable just before C
.
--------------------------C---P---
= ---C---P------------------------
= ---C---P---------C^-1---C-------
= ---C---P---C^-1---------C-------
= --(C^-1 · P · C)--------C-------
= ---P.conjugated_by(C)---C-------
Analogously, a Pauli product P can be moved from before a Clifford C in a circuit diagram to after the Clifford C by conjugating P by the inverse of C:
---P---C---------------------------
= -----C---P.conjugated_by(C^-1)---
Args | |
---|---|
clifford
|
The Clifford operation to conjugate by. This can be an
individual operation, or a tree of operations.
Note that the composite Clifford operation defined by a sequence
of operations is equivalent to a circuit containing those
operations in the given order. Somewhat counter-intuitively,
this means that the operations in the sequence are conjugated
onto the Pauli string in reverse order. For example,
|
Examples | |
---|---|
|
Returns | |
---|---|
The Pauli string conjugated by the given Clifford operation. |
controlled_by
controlled_by(
*control_qubits,
control_values: Optional[Union[cv.AbstractControlValues, Sequence[Union[int, Collection[int]]]]
] = None
) -> 'cirq.Operation'
Returns a controlled version of this operation. If no control_qubits are specified, returns self.
Args | |
---|---|
*control_qubits
|
Qubits to control the operation by. Required. |
control_values
|
For which control qubit values to apply the
operation. A sequence of the same length as control_qubits
where each entry is an integer (or set of integers)
corresponding to the qubit value (or set of possible values)
where that control is enabled. When all controls are enabled,
the operation is applied. If unspecified, control values
default to 1.
|
dense
dense(
qubits: Sequence[TKey]
) -> 'cirq.DensePauliString'
Returns a cirq.DensePauliString
version of this Pauli string.
This method satisfies the invariant P.dense(qubits).on(*qubits) == P
.
Args | |
---|---|
qubits
|
The implicit sequence of qubits used by the dense pauli
string. Specifically, if the returned dense Pauli string was
applied to these qubits (via its on method) then the result
would be a Pauli string equivalent to the receiving Pauli
string.
|
Returns | |
---|---|
A cirq.DensePauliString instance D such that D.on(*qubits)
equals the receiving cirq.PauliString instance P .
|
Raises | |
---|---|
ValueError
|
If the number of qubits is too small. |
equal_up_to_coefficient
equal_up_to_coefficient(
other: 'cirq.PauliString'
) -> bool
Returns true of self
and other
are equal pauli strings, ignoring the coefficient.
expectation_from_density_matrix
expectation_from_density_matrix(
state: np.ndarray,
qubit_map: Mapping[TKey, int],
*,
atol: float = 1e-07,
check_preconditions: bool = True
) -> float
Evaluate the expectation of this PauliString given a density matrix.
Compute the expectation value of this PauliString with respect to an array representing a density matrix. By convention expectation values are defined for Hermitian operators, and so this method will fail if this PauliString is non-Hermitian.
state
must be an array representation of a density matrix and have
shape (2 ** n, 2 ** n)
or (2, 2, ..., 2)
(2*n entries), where
state
is expressed over n qubits.
qubit_map
must assign an integer index to each qubit in this
PauliString that determines which bit position of a computational basis
state that qubit corresponds to. For example if state
represents
\(|0\rangle |+\rangle\) and q0, q1 = cirq.LineQubit.range(2)
then:
cirq.X(q0).expectation(state, qubit_map={q0: 0, q1: 1}) = 0
cirq.X(q0).expectation(state, qubit_map={q0: 1, q1: 0}) = 1
Args | |
---|---|
state
|
An array representing a valid density matrix. |
qubit_map
|
A map from all qubits used in this PauliString to the
indices of the qubits that state is defined over.
|
atol
|
Absolute numerical tolerance. |
check_preconditions
|
Whether to check that state represents a
valid density matrix.
|
Returns | |
---|---|
The expectation value of the input state. |
Raises | |
---|---|
NotImplementedError
|
If this PauliString is non-Hermitian or parameterized. |
TypeError
|
If the input state is not complex. |
ValueError
|
If the input state does not have the correct shape. |
expectation_from_state_vector
expectation_from_state_vector(
state_vector: np.ndarray,
qubit_map: Mapping[TKey, int],
*,
atol: float = 1e-07,
check_preconditions: bool = True
) -> float
Evaluate the expectation of this PauliString given a state vector.
Compute the expectation value of this PauliString with respect to a state vector. By convention expectation values are defined for Hermitian operators, and so this method will fail if this PauliString is non-Hermitian.
state
must be an array representation of a state vector and have
shape (2 ** n, )
or (2, 2, ..., 2)
(n entries) where state
is
expressed over n qubits.
qubit_map
must assign an integer index to each qubit in this
PauliString that determines which bit position of a computational basis
state that qubit corresponds to. For example if state
represents
\(|0\rangle |+\rangle\) and q0, q1 = cirq.LineQubit.range(2)
then:
cirq.X(q0).expectation(state, qubit_map={q0: 0, q1: 1}) = 0
cirq.X(q0).expectation(state, qubit_map={q0: 1, q1: 0}) = 1
Args | |
---|---|
state_vector
|
An array representing a valid state vector. |
qubit_map
|
A map from all qubits used in this PauliString to the
indices of the qubits that state_vector is defined over.
|
atol
|
Absolute numerical tolerance. |
check_preconditions
|
Whether to check that state_vector represents
a valid state vector.
|
Returns | |
---|---|
The expectation value of the input state. |
Raises | |
---|---|
NotImplementedError
|
If this PauliString is non-Hermitian or parameterized. |
TypeError
|
If the input state is not complex. |
ValueError
|
If the input state does not have the correct shape. |
frozen
frozen() -> 'cirq.PauliString'
Returns a cirq.PauliString
with the same contents.
get
get(
key: Any, default: Optional[TDefault] = None
) -> Union[pauli_gates.Pauli, TDefault, None]
Returns the cirq.Pauli
operation acting on qubit key
or default
if none exists.
items
items() -> ItemsView[TKey, pauli_gates.Pauli]
Returns (cirq.Qid, cirq.Pauli) pairs representing 1-qubit operations of pauli string.
keys
keys() -> KeysView[TKey]
Returns the sequence of qubits on which this pauli string acts.
map_qubits
map_qubits(
qubit_map: Dict[TKey, TKeyNew]
) -> 'cirq.PauliString[TKeyNew]'
Replaces every qubit q
in self.qubits
with qubit_map[q]
.
Args | |
---|---|
qubit_map
|
A map from qubits in the pauli string to new qubits. |
Returns | |
---|---|
A new PauliString with remapped qubits.
|
Raises | |
---|---|
ValueError
|
If the map does not contain an entry for all qubits in the pauli string. |
matrix
matrix(
qubits: Optional[Iterable[TKey]] = None
) -> np.ndarray
Returns the matrix of self in computational basis of qubits.
Args | |
---|---|
qubits
|
Ordered collection of qubits that determine the subspace
in which the matrix representation of the Pauli string is to
be computed. Qubits absent from self.qubits are acted on by
the identity. Defaults to self.qubits .
|
Raises | |
---|---|
NotImplementedError
|
If this PauliString is parameterized. |
mutable_copy
mutable_copy() -> 'cirq.MutablePauliString'
Returns a new cirq.MutablePauliString
with the same contents.
pass_operations_over
pass_operations_over(
ops: Iterable['cirq.Operation'], after_to_before: bool = False
) -> 'PauliString'
Determines how the Pauli string changes when conjugated by Cliffords.
The output and input pauli strings are related by a circuit equivalence. In particular, this circuit:
───ops───INPUT_PAULI_STRING───
will be equivalent to this circuit:
───OUTPUT_PAULI_STRING───ops───
up to global phase (assuming after_to_before
is not set).
If ops together have matrix C, the Pauli string has matrix P, and the output Pauli string has matrix P', then P' == C^-1 P C up to global phase.
Setting after_to_before
inverts the relationship, so that the output
is the input and the input is the output. Equivalently, it inverts C.
Args | |
---|---|
ops
|
The operations to move over the string. |
after_to_before
|
Determines whether the operations start after the pauli string, instead of before (and so are moving in the opposite direction). |
to_z_basis_ops
to_z_basis_ops() -> Iterator[cirq.Operation
]
Returns single qubit operations to convert the qubits to the computational basis.
transform_qubits
transform_qubits(
qubit_map: Union[Dict['cirq.Qid', 'cirq.Qid'], Callable[['cirq.Qid'], 'cirq.Qid']]
) -> Self
Returns the same operation, but with different qubits.
Args | |
---|---|
qubit_map
|
A function or a dict mapping each current qubit into a desired new qubit. |
Returns | |
---|---|
The receiving operation but with qubits transformed by the given function. |
Raises | |
---|---|
TypeError
|
qubit_map was not a function or dict mapping qubits to qubits. |
validate_args
validate_args(
qubits: Sequence['cirq.Qid']
)
Raises an exception if the qubits
don't match this operation's qid shape.
Call this method from a subclass's with_qubits
method.
Args | |
---|---|
qubits
|
The new qids for the operation. |
Raises | |
---|---|
ValueError
|
The operation had qids that don't match it's qid shape. |
values
values() -> ValuesView[cirq.Pauli
]
Ordered sequence of cirq.Pauli
gates acting on self.keys()
.
with_classical_controls
with_classical_controls(
*conditions
) -> 'cirq.Operation'
Returns a classically controlled version of this operation.
An operation that is classically controlled is executed iff all
conditions evaluate to True. Conditions can be either a measurement key
or a user-specified cirq.Condition
. A measurement key evaluates to
True iff any qubit in the corresponding measurement operation evaluated
to a non-zero value; cirq.Condition
supports more complex,
user-defined conditions.
If no conditions are specified, returns self.
The classical control will remove any tags on the existing operation, since tags are fragile, and we always opt to get rid of the tags when the underlying operation is changed.
Args | |
---|---|
*conditions
|
A list of measurement keys, strings that can be parsed into measurement keys, or sympy expressions where the free symbols are measurement key strings. |
Returns | |
---|---|
A ClassicallyControlledOperation wrapping the operation. If no conditions
are specified, returns self.
|
with_coefficient
with_coefficient(
new_coefficient: 'cirq.TParamValComplex'
) -> 'PauliString'
Returns a new PauliString
with self.coefficient
replaced with new_coefficient
.
with_probability
with_probability(
probability: 'cirq.TParamVal'
) -> 'cirq.Operation'
Creates a probabilistic channel with this operation.
Args | |
---|---|
probability
|
floating point value between 0 and 1, giving the probability this gate is applied. |
Returns | |
---|---|
cirq.RandomGateChannel that applies self with probability
probability and the identity with probability 1-p .
|
Raises | |
---|---|
NotImplementedError
|
if called on an operation that lacks a gate. |
with_qubits
with_qubits(
*new_qubits
) -> 'PauliString'
Returns a new PauliString
with self.qubits
mapped to new_qubits
.
Args | |
---|---|
new_qubits
|
The new qubits to replace self.qubits by.
|
Returns | |
---|---|
PauliString with mapped qubits.
|
Raises | |
---|---|
ValueError
|
If len(new_qubits) != len(self.qubits) .
|
with_tags
with_tags(
*new_tags
) -> 'cirq.Operation'
Creates a new TaggedOperation, with this op and the specified tags.
This method can be used to attach meta-data to specific operations without affecting their functionality. The intended usage is to attach classes intended for this purpose or strings to mark operations for specific usage that will be recognized by consumers. Specific examples include ignoring this operation in optimization passes, hardware-specific functionality, or circuit diagram customizability.
Tags can be a list of any type of object that is useful to identify this operation as long as the type is hashable. If you wish the resulting operation to be eventually serialized into JSON, you should also restrict the operation to be JSON serializable.
Args | |
---|---|
*new_tags
|
The tags to wrap this operation in. |
without_classical_controls
without_classical_controls() -> 'cirq.Operation'
Removes all classical controls from the operation.
This function removes all classical controls gating the operation. It acts recursively, so that all classical control wrappers are always removed from the current operation.
If there are no classical controls on the operation, it will return
self
.
Since tags are fragile, this will also remove any tags from the operation,
when called on TaggedOperation
(unless there are no classical controls on it).
If a TaggedOperation
is under all the classical control layers,
that TaggedOperation
will be returned from this function.
Returns | |
---|---|
The operation with all classical controls removed. |
zip_items
zip_items(
other: 'cirq.PauliString[TKey]'
) -> Iterator[Tuple[TKey, Tuple[pauli_gates.Pauli, pauli_gates.Pauli]]]
Combines pauli operations from pauli strings in a qubit-by-qubit fashion.
For every qubit that has a cirq.Pauli
operation acting on it in both self
and other
,
the method yields a tuple corresponding to (qubit, (pauli_in_self, pauli_in_other))
.
Args | |
---|---|
other
|
The other cirq.PauliString to zip pauli operations with.
|
Returns | |
---|---|
A sequence of (qubit, (pauli_in_self, pauli_in_other)) tuples for every qubit
that has a cirq.Pauli operation acting on it in both self and `other.
|
zip_paulis
zip_paulis(
other: 'cirq.PauliString'
) -> Iterator[Tuple[pauli_gates.Pauli, pauli_gates.Pauli]]
Combines pauli operations from pauli strings in a qubit-by-qubit fashion.
For every qubit that has a cirq.Pauli
operation acting on it in both self
and other
,
the method yields a tuple corresponding to (pauli_in_self, pauli_in_other)
.
Args | |
---|---|
other
|
The other cirq.PauliString to zip pauli operations with.
|
Returns | |
---|---|
A sequence of (pauli_in_self, pauli_in_other) tuples for every qubit
that has a cirq.Pauli operation acting on it in both self and `other.
|
__add__
__add__(
other
)
__bool__
__bool__()
__contains__
__contains__(
key: TKey
) -> bool
__eq__
__eq__(
other: _SupportsValueEquality
) -> bool
__getitem__
__getitem__(
key: TKey
) -> cirq.Pauli
__iter__
__iter__() -> Iterator[TKey]
__len__
__len__() -> int
__mul__
__mul__(
other
)
__ne__
__ne__(
other: _SupportsValueEquality
) -> bool
__neg__
__neg__() -> 'PauliString'
__pos__
__pos__() -> 'PauliString'
__pow__
__pow__(
power
)
__radd__
__radd__(
other
)
__rmul__
__rmul__(
other
) -> 'PauliString'
__rpow__
__rpow__(
base
)
__rsub__
__rsub__(
other
)
__sub__
__sub__(
other
)
__truediv__
__truediv__(
other
)