# Source code for sympy.physics.quantum.dagger

"""Hermitian conjugation."""

from __future__ import print_function, division

from sympy.core import Expr
from sympy.functions.elementary.complexes import adjoint

__all__ = [
'Dagger'
]

[docs]class Dagger(adjoint):
"""General Hermitian conjugate operation.

Take the Hermetian conjugate of an argument [1]_. For matrices this
operation is equivalent to transpose and complex conjugate [2]_.

Parameters
==========

arg : Expr
The sympy expression that we want to take the dagger of.

Examples
========

Daggering various quantum objects:

>>> from sympy.physics.quantum.dagger import Dagger
>>> from sympy.physics.quantum.state import Ket, Bra
>>> from sympy.physics.quantum.operator import Operator
>>> Dagger(Ket('psi'))
<psi|
>>> Dagger(Bra('phi'))
|phi>
>>> Dagger(Operator('A'))
Dagger(A)

Inner and outer products::

>>> from sympy.physics.quantum import InnerProduct, OuterProduct
>>> Dagger(InnerProduct(Bra('a'), Ket('b')))
<b|a>
>>> Dagger(OuterProduct(Ket('a'), Bra('b')))
|b><a|

Powers, sums and products::

>>> A = Operator('A')
>>> B = Operator('B')
>>> Dagger(A*B)
Dagger(B)*Dagger(A)
>>> Dagger(A+B)
Dagger(A) + Dagger(B)
>>> Dagger(A**2)
Dagger(A)**2

Dagger also seamlessly handles complex numbers and matrices::

>>> from sympy import Matrix, I
>>> m = Matrix([[1,I],[2,I]])
>>> m
Matrix([
[1, I],
[2, I]])
>>> Dagger(m)
Matrix([
[ 1,  2],
[-I, -I]])

References
==========

.. [1] http://en.wikipedia.org/wiki/Hermitian_adjoint
.. [2] http://en.wikipedia.org/wiki/Hermitian_transpose
"""

def __new__(cls, arg):
if hasattr(arg, 'adjoint'):
obj = arg.adjoint()
elif hasattr(arg, 'conjugate') and hasattr(arg, 'transpose'):
obj = arg.conjugate().transpose()
if obj is not None:
return obj
return Expr.__new__(cls, arg)

adjoint.__name__ = "Dagger"
adjoint._sympyrepr = lambda a, b: "Dagger(%s)" % b._print(a.args[0])