qnet.algebra.core.operator_algebra module

This module features classes and functions to define and manipulate symbolic Operator expressions. For more details see Operator Algebra.

For a list of all properties and methods of an operator object, see the documentation for the basic Operator class.

Summary

Classes:

Adjoint Symbolic Adjoint of an operator
Commutator Commutator of two operators
LocalOperator Base class for “known” operators on a LocalSpace
LocalSigma Level flip operator between two levels of a LocalSpace
NullSpaceProjector Projection operator onto the nullspace of its operand
Operator Base class for all quantum operators.
OperatorDerivative Symbolic partial derivative of an operator
OperatorIndexedSum Indexed sum over operators
OperatorPlus Sum of Operators
OperatorPlusMinusCC An operator plus or minus its complex conjugate
OperatorSymbol Symbolic operator
OperatorTimes Product of operators
OperatorTrace (Partial) trace of an operator
PseudoInverse Unevaluated pseudo-inverse \(\Op{X}^+\) of an operator \(\Op{X}\)
ScalarTimesOperator Product of a Scalar coefficient and an Operator

Functions:

LocalProjector A projector onto a specific level of a LocalSpace
adjoint Return the adjoint of an obj.
decompose_space Simplifies OperatorTrace expressions over tensor-product spaces by turning it into iterated partial traces.
factor_coeff Factor out coefficients of all factors.
factor_for_trace Given a LocalSpace ls to take the partial trace over and an operator op, factor the trace such that operators acting on disjoint degrees of freedom are pulled out of the trace.
get_coeffs Create a dictionary with all Operator terms of the expression (understood as a sum) as keys and their coefficients as values.
rewrite_with_operator_pm_cc Try to rewrite expr using OperatorPlusMinusCC

Data:

II IdentityOperator constant (singleton) object.
IdentityOperator IdentityOperator constant (singleton) object.
ZeroOperator ZeroOperator constant (singleton) object.

__all__: Adjoint, Commutator, II, IdentityOperator, LocalOperator, LocalProjector, LocalSigma, NullSpaceProjector, Operator, OperatorDerivative, OperatorIndexedSum, OperatorPlus, OperatorPlusMinusCC, OperatorSymbol, OperatorTimes, OperatorTrace, PseudoInverse, ScalarTimesOperator, ZeroOperator, adjoint, decompose_space, factor_coeff, factor_for_trace, get_coeffs, rewrite_with_operator_pm_cc, tr

Reference

class qnet.algebra.core.operator_algebra.Operator(*args, **kwargs)[source]

Bases: qnet.algebra.core.abstract_quantum_algebra.QuantumExpression

Base class for all quantum operators.

pseudo_inverse()[source]

Pseudo-inverse \(\Op{X}^+\) of the operator \(\Op{X}\)

It is defined via the relationship

\[\Op{X} \Op{X}^+ \Op{X} = \Op{X} \ \Op{X}^+ \Op{X} \Op{X}^+ = \Op{X}^+ \ (\Op{X}^+ \Op{X})^\dagger = \Op{X}^+ \Op{X} \ (\Op{X} \Op{X}^+)^\dagger = \Op{X} \Op{X}^+\]
expand_in_basis(basis_states=None, hermitian=False)[source]

Write the operator as an expansion into all KetBras spanned by basis_states.

Parameters:
  • basis_states (list or None) – List of basis states (State instances) into which to expand the operator. If None, use the operator’s space.basis_states
  • hermitian (bool) – If True, assume that the operator is Hermitian and represent all elements in the lower triangle of the expansion via OperatorPlusMinusCC. This is meant to enhance readability
Raises:

BasisNotSetError – If basis_states is None and the operator’s Hilbert space has no well-defined basis

Example

>>> hs = LocalSpace(1, basis=('g', 'e'))
>>> op = LocalSigma('g', 'e', hs=hs) + LocalSigma('e', 'g', hs=hs)
>>> print(ascii(op, sig_as_ketbra=False))
sigma_e,g^(1) + sigma_g,e^(1)
>>> print(ascii(op.expand_in_basis()))
|e><g|^(1) + |g><e|^(1)
>>> print(ascii(op.expand_in_basis(hermitian=True)))
|g><e|^(1) + c.c.
class qnet.algebra.core.operator_algebra.LocalOperator(*args, hs)[source]

Bases: qnet.algebra.core.operator_algebra.Operator

Base class for “known” operators on a LocalSpace

All LocalOperator instances have known algebraic properties and a fixed associated identifier (symbol) that is used when printing that operator. A custom identifier can be used through the associated LocalSpace’s local_identifiers parameter. For example:

>>> hs1_custom = LocalSpace(1, local_identifiers={'Destroy': 'b'})
>>> b = Destroy(hs=hs1_custom)
>>> ascii(b)
'b^(1)'

Note

It is recommended that subclasses use the properties_for_args() class decorator if they define any position arguments (via the _arg_names class attribute)

simplifications = [<function implied_local_space.<locals>.kwargs_to_local_space>]
space

Hilbert space of the operator (LocalSpace instance)

args

The positional arguments used for instantiating the operator

kwargs

The keyword arguments used for instantiating the operator

identifier

The identifier (symbol) that is used when printing the operator.

A custom identifier can be used through the associated LocalSpace’s local_identifiers parameter. For example:

>>> a = Destroy(hs=1)
>>> a.identifier
'a'
>>> hs1_custom = LocalSpace(1, local_identifiers={'Destroy': 'b'})
>>> b = Destroy(hs=hs1_custom)
>>> b.identifier
'b'
>>> ascii(b)
'b^(1)'
class qnet.algebra.core.operator_algebra.OperatorSymbol(label, *sym_args, hs)[source]

Bases: qnet.algebra.core.abstract_quantum_algebra.QuantumSymbol, qnet.algebra.core.operator_algebra.Operator

Symbolic operator

See QuantumSymbol.

qnet.algebra.core.operator_algebra.IdentityOperator = IdentityOperator[source]

IdentityOperator constant (singleton) object.

qnet.algebra.core.operator_algebra.II = IdentityOperator

IdentityOperator constant (singleton) object.

qnet.algebra.core.operator_algebra.ZeroOperator = ZeroOperator[source]

ZeroOperator constant (singleton) object.

class qnet.algebra.core.operator_algebra.LocalSigma(j, k, *, hs)[source]

Bases: qnet.algebra.core.operator_algebra.LocalOperator

Level flip operator between two levels of a LocalSpace

\[\Op{\sigma}_{jk}^{\rm hs} = \left| j\right\rangle_{\rm hs} \left \langle k \right |_{\rm hs}\]

For \(j=k\) this becomes a projector \(\Op{P}_k\) onto the eigenstate \(\ket{k}\); see LocalProjector.

Parameters:
  • j (int or str) – The label or index identifying \(\ket{j}\)
  • k (int or str) – The label or index identifying \(\ket{k}\)
  • hs (LocalSpace or int or str) – The Hilbert space on which the operator acts. If an int or a str, an implicit Hilbert space will be constructed as a subclass of LocalSpace, as configured by init_algebra().

Note

The parameters j or k may be an integer or a string. A string refers to the label of an eigenstate in the basis of hs, which needs to be set. An integer refers to the (zero-based) index of eigenstate of the Hilbert space. This works if hs has an unknown dimension. Assuming the Hilbert space has a defined basis, using integer or string labels is equivalent:

>>> hs = LocalSpace('tls', basis=('g', 'e'))
>>> LocalSigma(0, 1, hs=hs) == LocalSigma('g', 'e', hs=hs)
True
Raises:ValueError – If j or k are invalid value for the given hs

Printers should represent this operator either in braket notation, or using the operator identifier

>>> LocalSigma(0, 1, hs=0).identifier
'sigma'

For j == k, an alternative (fixed) identifier may be used

>>> LocalSigma(0, 0, hs=0)._identifier_projector
'Pi'
simplifications = [<function implied_local_space.<locals>.kwargs_to_local_space>, <function match_replace>]
args

The two eigenstate labels j and k that the operator connects

index_j

Index j or (zero-based) index of the label j in the basis

index_k

Index k or (zero-based) index of the label k in the basis

raise_jk(j_incr=0, k_incr=0)[source]

Return a new LocalSigma instance with incremented j, k, on the same Hilbert space:

\[\Op{\sigma}_{jk}^{\rm hs} \rightarrow \Op{\sigma}_{j'k'}^{\rm hs}\]

This is the result of multiplying \(\Op{\sigma}_{jk}^{\rm hs}\) with any raising or lowering operators.

If \(j'\) or \(k'\) are outside the Hilbert space \({\rm hs}\), the result is the ZeroOperator .

Parameters:
  • j_incr (int) – The increment between labels \(j\) and \(j'\)
  • k_incr (int) – The increment between labels \(k\) and \(k'\). Both increments may be negative.
j

The j argument.

k

The k argument.

qnet.algebra.core.operator_algebra.LocalProjector(j, *, hs)[source]

A projector onto a specific level of a LocalSpace

Parameters:
  • j (int or str) – The label or index identifying the state onto which is projected
  • hs (HilbertSpace) – The Hilbert space on which the operator acts
class qnet.algebra.core.operator_algebra.OperatorPlus(*operands, **kwargs)[source]

Bases: qnet.algebra.core.abstract_quantum_algebra.QuantumPlus, qnet.algebra.core.operator_algebra.Operator

Sum of Operators

simplifications = [<function assoc>, <function scalars_to_op>, <function orderby>, <function collect_summands>, <function match_replace_binary>]
class qnet.algebra.core.operator_algebra.OperatorTimes(*operands, **kwargs)[source]

Bases: qnet.algebra.core.abstract_quantum_algebra.QuantumTimes, qnet.algebra.core.operator_algebra.Operator

Product of operators

This serves both as a product within a Hilbert space as well as a tensor product.

simplifications = [<function assoc>, <function orderby>, <function filter_neutral>, <function match_replace_binary>]
class qnet.algebra.core.operator_algebra.ScalarTimesOperator(coeff, term)[source]

Bases: qnet.algebra.core.operator_algebra.Operator, qnet.algebra.core.abstract_quantum_algebra.ScalarTimesQuantumExpression

Product of a Scalar coefficient and an Operator

simplifications = [<function match_replace>]
static has_minus_prefactor(c)[source]

For a scalar object c, determine whether it is prepended by a “-” sign.

class qnet.algebra.core.operator_algebra.OperatorDerivative(op, *, derivs, vals=None)[source]

Bases: qnet.algebra.core.abstract_quantum_algebra.QuantumDerivative, qnet.algebra.core.operator_algebra.Operator

Symbolic partial derivative of an operator

See QuantumDerivative.

class qnet.algebra.core.operator_algebra.Commutator(A, B)[source]

Bases: qnet.algebra.core.abstract_quantum_algebra.QuantumOperation, qnet.algebra.core.operator_algebra.Operator

Commutator of two operators

\[[\Op{A}, \Op{B}] = \Op{A}\Op{B} - \Op{A}\Op{B}\]
simplifications = [<function scalars_to_op>, <function disjunct_hs_zero>, <function commutator_order>, <function match_replace>]
order_key

alias of qnet.utils.ordering.FullCommutativeHSOrder

A

Left side of the commutator

B

Left side of the commutator

doit(classes=None, recursive=True, **kwargs)[source]

Write out commutator

Write out the commutator according to its definition \([\Op{A}, \Op{B}] = \Op{A}\Op{B} - \Op{A}\Op{B}\).

See Expression.doit().

class qnet.algebra.core.operator_algebra.OperatorTrace(op, *, over_space)[source]

Bases: qnet.algebra.core.abstract_quantum_algebra.SingleQuantumOperation, qnet.algebra.core.operator_algebra.Operator

(Partial) trace of an operator

Trace of an operator op ($Op{O}) over the degrees of freedom of a Hilbert space over_space ($mathcal{H}$):

\[{\rm Tr}_{\mathcal{H}} \Op{O}\]
Parameters:
  • over_space (HilbertSpace) – The degrees of freedom to trace over
  • op (Operator) – The operator to take the trace of.
simplifications = [<function scalars_to_op>, <function implied_local_space.<locals>.kwargs_to_local_space>, <function match_replace>]
kwargs

The dictionary of keyword-only arguments for the instantiation of the Expression

operand

The operator that the operation acts on

space

Hilbert space of the operation result

class qnet.algebra.core.operator_algebra.Adjoint(op, **kwargs)[source]

Bases: qnet.algebra.core.abstract_quantum_algebra.QuantumAdjoint, qnet.algebra.core.operator_algebra.Operator

Symbolic Adjoint of an operator

simplifications = [<function scalars_to_op>, <function delegate_to_method.<locals>._delegate_to_method>]
class qnet.algebra.core.operator_algebra.OperatorPlusMinusCC(op, *, sign=1)[source]

Bases: qnet.algebra.core.abstract_quantum_algebra.SingleQuantumOperation, qnet.algebra.core.operator_algebra.Operator

An operator plus or minus its complex conjugate

kwargs

The dictionary of keyword-only arguments for the instantiation of the Expression

minimal_kwargs

A “minimal” dictionary of keyword-only arguments, i.e. a subset of kwargs that may exclude default options

doit(classes=None, recursive=True, **kwargs)[source]

Write out the complex conjugate summand

See Expression.doit().

class qnet.algebra.core.operator_algebra.PseudoInverse(op, **kwargs)[source]

Bases: qnet.algebra.core.abstract_quantum_algebra.SingleQuantumOperation, qnet.algebra.core.operator_algebra.Operator

Unevaluated pseudo-inverse \(\Op{X}^+\) of an operator \(\Op{X}\)

It is defined via the relationship

\[\begin{split}\Op{X} \Op{X}^+ \Op{X} = \Op{X} \\ \Op{X}^+ \Op{X} \Op{X}^+ = \Op{X}^+ \\ (\Op{X}^+ \Op{X})^\dagger = \Op{X}^+ \Op{X} \\ (\Op{X} \Op{X}^+)^\dagger = \Op{X} \Op{X}^+\end{split}\]
simplifications = [<function scalars_to_op>, <function delegate_to_method.<locals>._delegate_to_method>]
class qnet.algebra.core.operator_algebra.NullSpaceProjector(op, **kwargs)[source]

Bases: qnet.algebra.core.abstract_quantum_algebra.SingleQuantumOperation, qnet.algebra.core.operator_algebra.Operator

Projection operator onto the nullspace of its operand

Returns the operator \(\mathcal{P}_{{\rm Ker} X}\) with

\[\begin{split}X \mathcal{P}_{{\rm Ker} X} = 0 \Leftrightarrow X (1 - \mathcal{P}_{{\rm Ker} X}) = X \\ \mathcal{P}_{{\rm Ker} X}^\dagger = \mathcal{P}_{{\rm Ker} X} = \mathcal{P}_{{\rm Ker} X}^2\end{split}\]
simplifications = [<function scalars_to_op>, <function match_replace>]
class qnet.algebra.core.operator_algebra.OperatorIndexedSum(term, *ranges)[source]

Bases: qnet.algebra.core.abstract_quantum_algebra.QuantumIndexedSum, qnet.algebra.core.operator_algebra.Operator

Indexed sum over operators

simplifications = [<function assoc_indexed>, <function scalars_to_op>, <function indexed_sum_over_kronecker>, <function indexed_sum_over_const>, <function match_replace>]
qnet.algebra.core.operator_algebra.factor_for_trace(ls, op)[source]

Given a LocalSpace ls to take the partial trace over and an operator op, factor the trace such that operators acting on disjoint degrees of freedom are pulled out of the trace. If the operator acts trivially on ls the trace yields only a pre-factor equal to the dimension of ls. If there are LocalSigma operators among a product, the trace’s cyclical property is used to move to sandwich the full product by LocalSigma operators:

\[{\rm Tr} A \sigma_{jk} B = {\rm Tr} \sigma_{jk} B A \sigma_{jj}\]
Parameters:
  • ls (HilbertSpace) – Degree of Freedom to trace over
  • op (Operator) – Operator to take the trace of
Return type:

Operator

Returns:

The (partial) trace over the operator’s spc-degrees of freedom

qnet.algebra.core.operator_algebra.decompose_space(H, A)[source]

Simplifies OperatorTrace expressions over tensor-product spaces by turning it into iterated partial traces.

Parameters:
Returns:

Iterative partial trace expression

Return type:

Operator

qnet.algebra.core.operator_algebra.get_coeffs(expr, expand=False, epsilon=0.0)[source]

Create a dictionary with all Operator terms of the expression (understood as a sum) as keys and their coefficients as values.

The returned object is a defaultdict that return 0. if a term/key doesn’t exist.

Parameters:
  • expr – The operator expression to get all coefficients from.
  • expand – Whether to expand the expression distributively.
  • epsilon – If non-zero, drop all Operators with coefficients that have absolute value less than epsilon.
Returns:

A dictionary {op1: coeff1, op2: coeff2, ...}

Return type:

dict

qnet.algebra.core.operator_algebra.factor_coeff(cls, ops, kwargs)[source]

Factor out coefficients of all factors.

qnet.algebra.core.operator_algebra.adjoint(obj)[source]

Return the adjoint of an obj.

qnet.algebra.core.operator_algebra.rewrite_with_operator_pm_cc(expr)[source]

Try to rewrite expr using OperatorPlusMinusCC

Example

>>> A = OperatorSymbol('A', hs=1)
>>> sum = A + A.dag()
>>> sum2 = rewrite_with_operator_pm_cc(sum)
>>> print(ascii(sum2))
A^(1) + c.c.