U
    ZÊ¹jdL  ã                   @   s  d Z ddlmZ ddlmZ ddlmZ ddlmZm	Z	 ddl
mZ ddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZmZ ddlmZ ddddddgZG dd„ deƒZG dd„ deƒZG dd„ deƒZG dd„ deƒZG dd„ deƒZG dd„ deƒZdS )a  Quantum mechanical operators.

TODO:

* Fix early 0 in apply_operators.
* Debug and test apply_operators.
* Get cse working with classes in this file.
* Doctests and documentation of special methods for InnerProduct, Commutator,
  AntiCommutator, represent, apply_operators.
é    )ÚOptional)ÚAdd)ÚExpr)Ú
DerivativeÚexpand)ÚMul©Úoo©ÚS©Ú
prettyForm)ÚDagger)ÚQExprÚdispatch_method)ÚeyeÚOperatorÚHermitianOperatorÚUnitaryOperatorÚIdentityOperatorÚOuterProductÚDifferentialOperatorc                   @   s²   e Zd ZU dZdZee ed< dZee ed< e	dd„ ƒZ
dZdd	„ ZeZd
d„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ ZeZdd„ Zd d!„ ZdS )"r   a
  Base class for non-commuting quantum operators.

    An operator maps between quantum states [1]_. In quantum mechanics,
    observables (including, but not limited to, measured physical values) are
    represented as Hermitian operators [2]_.

    Parameters
    ==========

    args : tuple
        The list of numbers or parameters that uniquely specify the
        operator. For time-dependent operators, this will include the time.

    Examples
    ========

    Create an operator and examine its attributes::

        >>> from sympy.physics.quantum import Operator
        >>> from sympy import I
        >>> A = Operator('A')
        >>> A
        A
        >>> A.hilbert_space
        H
        >>> A.label
        (A,)
        >>> A.is_commutative
        False

    Create another operator and do some arithmetic operations::

        >>> B = Operator('B')
        >>> C = 2*A*A + I*B
        >>> C
        2*A**2 + I*B

    Operators do not commute::

        >>> A.is_commutative
        False
        >>> B.is_commutative
        False
        >>> A*B == B*A
        False

    Polymonials of operators respect the commutation properties::

        >>> e = (A+B)**3
        >>> e.expand()
        A*B*A + A*B**2 + A**2*B + A**3 + B*A*B + B*A**2 + B**2*A + B**3

    Operator inverses are handle symbolically::

        >>> A.inv()
        A**(-1)
        >>> A*A.inv()
        1

    References
    ==========

    .. [1] https://en.wikipedia.org/wiki/Operator_%28physics%29
    .. [2] https://en.wikipedia.org/wiki/Observable
    NÚis_hermitianÚ
is_unitaryc                 C   s   dS )N)ÚO© ©Úselfr   r   ú]/var/www/html/bwave/python/venv/lib/python3.8/site-packages/sympy/physics/quantum/operator.pyÚdefault_argsj   s    zOperator.default_argsú,c                 G   s   | j jS ©N)Ú	__class__Ú__name__©r   ÚprinterÚargsr   r   r   Ú_print_operator_namet   s    zOperator._print_operator_namec                 G   s   t | jjƒS r!   )r   r"   r#   r$   r   r   r   Ú_print_operator_name_prettyy   s    z$Operator._print_operator_name_prettyc                 G   sF   t | jƒdkr| j|f|žŽ S d| j|f|žŽ | j|f|žŽ f S d S )Né   ú%s(%s))ÚlenÚlabelÚ_print_labelr'   r$   r   r   r   Ú_print_contents|   s    þzOperator._print_contentsc                 G   sf   t | jƒdkr| j|f|žŽ S | j|f|žŽ }| j|f|žŽ }t|jddd�Ž }t| |¡Ž }|S d S )Nr)   ú(ú)©ÚleftÚright)r+   r,   Ú_print_label_prettyr(   r   Úparensr3   ©r   r%   r&   ÚpformZlabel_pformr   r   r   Ú_print_contents_pretty…   s    ÿzOperator._print_contents_prettyc                 G   sF   t | jƒdkr| j|f|žŽ S d| j|f|žŽ | j|f|žŽ f S d S )Nr)   z%s\left(%s\right))r+   r,   Z_print_label_latexÚ_print_operator_name_latexr$   r   r   r   Ú_print_contents_latex‘   s    þzOperator._print_contents_latexc                 K   s   t | d|f|ŽS )z:Evaluate [self, other] if known, return None if not known.Ú_eval_commutator©r   ©r   ÚotherÚoptionsr   r   r   r;   ž   s    zOperator._eval_commutatorc                 K   s   t | d|f|ŽS )z Evaluate [self, other] if known.Ú_eval_anticommutatorr<   r=   r   r   r   r@   ¢   s    zOperator._eval_anticommutatorc                 K   s   t | d|f|ŽS )NÚ_apply_operatorr<   ©r   Úketr?   r   r   r   rA   ª   s    zOperator._apply_operatorc                 K   s   d S r!   r   ©r   Úbrar?   r   r   r   Ú_apply_from_right_to­   s    zOperator._apply_from_right_toc                 G   s   t dƒ‚d S )Nzmatrix_elements is not defined)ÚNotImplementedError)r   r&   r   r   r   Úmatrix_element°   s    zOperator.matrix_elementc                 C   s   |   ¡ S r!   ©Ú_eval_inverser   r   r   r   Úinverse³   s    zOperator.inversec                 C   s   | d S ©Néÿÿÿÿr   r   r   r   r   rJ   ¸   s    zOperator._eval_inversec                 C   s   t |tƒr| S t| |ƒS r!   )Ú
isinstancer   r   ©r   r>   r   r   r   Ú__mul__»   s    
zOperator.__mul__)r#   Ú
__module__Ú__qualname__Ú__doc__r   r   ÚboolÚ__annotations__r   Úclassmethodr   Z_label_separatorr'   r9   r(   r.   r8   r:   r;   r@   rA   rF   rH   rK   ÚinvrJ   rP   r   r   r   r   r   &   s*   
A
	c                   @   s$   e Zd ZdZdZdd„ Zdd„ ZdS )r   a”  A Hermitian operator that satisfies H == Dagger(H).

    Parameters
    ==========

    args : tuple
        The list of numbers or parameters that uniquely specify the
        operator. For time-dependent operators, this will include the time.

    Examples
    ========

    >>> from sympy.physics.quantum import Dagger, HermitianOperator
    >>> H = HermitianOperator('H')
    >>> Dagger(H)
    H
    Tc                 C   s   t | tƒr| S t | ¡S d S r!   )rN   r   r   rJ   r   r   r   r   rJ   Ø   s    
zHermitianOperator._eval_inversec                 C   s8   t | tƒr,|jr"ddlm} |jS |jr,| S t | |¡S )Nr   r
   )	rN   r   Zis_evenÚsympy.core.singletonr   ZOneZis_oddr   Ú_eval_power)r   Úexpr   r   r   r   rY   Þ   s    
zHermitianOperator._eval_powerN)r#   rQ   rR   rS   r   rJ   rY   r   r   r   r   r   Ã   s   c                   @   s   e Zd ZdZdZdd„ ZdS )r   a’  A unitary operator that satisfies U*Dagger(U) == 1.

    Parameters
    ==========

    args : tuple
        The list of numbers or parameters that uniquely specify the
        operator. For time-dependent operators, this will include the time.

    Examples
    ========

    >>> from sympy.physics.quantum import Dagger, UnitaryOperator
    >>> U = UnitaryOperator('U')
    >>> U*Dagger(U)
    1
    Tc                 C   s   |   ¡ S r!   rI   r   r   r   r   Ú_eval_adjointý   s    zUnitaryOperator._eval_adjointN)r#   rQ   rR   rS   r   r[   r   r   r   r   r   ê   s   c                   @   s˜   e Zd ZdZdZdZedd„ ƒZedd„ ƒZ	dd„ Z
d	d
„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd „ Zd!S )"r   aš  An identity operator I that satisfies op * I == I * op == op for any
    operator op.

    Parameters
    ==========

    N : Integer
        Optional parameter that specifies the dimension of the Hilbert space
        of operator. This is used when generating a matrix representation.

    Examples
    ========

    >>> from sympy.physics.quantum import IdentityOperator
    >>> IdentityOperator()
    I
    Tc                 C   s   | j S r!   )ÚNr   r   r   r   Ú	dimension  s    zIdentityOperator.dimensionc                 C   s   t fS r!   r   r   r   r   r   r     s    zIdentityOperator.default_argsc                 O   s>   t |ƒdkrtd| ƒ‚t |ƒdkr4|d r4|d nt| _d S )N)r   r)   z"0 or 1 parameters expected, got %sr)   r   )r+   Ú
ValueErrorr	   r\   )r   r&   Úhintsr   r   r   Ú__init__  s    zIdentityOperator.__init__c                 K   s   t jS r!   )r   ZZero©r   r>   r_   r   r   r   r;   #  s    z!IdentityOperator._eval_commutatorc                 K   s   d| S )Né   r   ra   r   r   r   r@   &  s    z%IdentityOperator._eval_anticommutatorc                 C   s   | S r!   r   r   r   r   r   rJ   )  s    zIdentityOperator._eval_inversec                 C   s   | S r!   r   r   r   r   r   r[   ,  s    zIdentityOperator._eval_adjointc                 K   s   |S r!   r   rB   r   r   r   rA   /  s    z IdentityOperator._apply_operatorc                 K   s   |S r!   r   rD   r   r   r   rF   2  s    z%IdentityOperator._apply_from_right_toc                 C   s   | S r!   r   )r   rZ   r   r   r   rY   5  s    zIdentityOperator._eval_powerc                 G   s   dS ©NÚIr   r$   r   r   r   r.   8  s    z IdentityOperator._print_contentsc                 G   s   t dƒS rc   r   r$   r   r   r   r8   ;  s    z'IdentityOperator._print_contents_prettyc                 G   s   dS )Nz{\mathcal{I}}r   r$   r   r   r   r:   >  s    z&IdentityOperator._print_contents_latexc                 C   s   t |ttfƒr|S t| |ƒS r!   )rN   r   r   r   rO   r   r   r   rP   A  s    zIdentityOperator.__mul__c                 K   sF   | j r| j tkrtdƒ‚| dd¡}|dkr<tdd|  ƒ‚t| j ƒS )NzCCannot represent infinite dimensional identity operator as a matrixÚformatZsympyzRepresentation in format z%s not implemented.)r\   r	   rG   Úgetr   )r   r?   re   r   r   r   Ú_represent_default_basisH  s    ÿz)IdentityOperator._represent_default_basisN)r#   rQ   rR   rS   r   r   Úpropertyr]   rV   r   r`   r;   r@   rJ   r[   rA   rF   rY   r.   r8   r:   rP   rg   r   r   r   r   r     s(   

c                   @   sl   e Zd ZdZdZdd„ Zedd„ ƒZedd„ ƒZd	d
„ Z	dd„ Z
dd„ Zdd„ Zdd„ Zdd„ Zdd„ ZdS )r   aÙ  An unevaluated outer product between a ket and bra.

    This constructs an outer product between any subclass of ``KetBase`` and
    ``BraBase`` as ``|a><b|``. An ``OuterProduct`` inherits from Operator as they act as
    operators in quantum expressions.  For reference see [1]_.

    Parameters
    ==========

    ket : KetBase
        The ket on the left side of the outer product.
    bar : BraBase
        The bra on the right side of the outer product.

    Examples
    ========

    Create a simple outer product by hand and take its dagger::

        >>> from sympy.physics.quantum import Ket, Bra, OuterProduct, Dagger
        >>> from sympy.physics.quantum import Operator

        >>> k = Ket('k')
        >>> b = Bra('b')
        >>> op = OuterProduct(k, b)
        >>> op
        |k><b|
        >>> op.hilbert_space
        H
        >>> op.ket
        |k>
        >>> op.bra
        <b|
        >>> Dagger(op)
        |b><k|

    In simple products of kets and bras outer products will be automatically
    identified and created::

        >>> k*b
        |k><b|

    But in more complex expressions, outer products are not automatically
    created::

        >>> A = Operator('A')
        >>> A*k*b
        A*|k>*<b|

    A user can force the creation of an outer product in a complex expression
    by using parentheses to group the ket and bra::

        >>> A*(k*b)
        A*|k><b|

    References
    ==========

    .. [1] https://en.wikipedia.org/wiki/Outer_product
    Fc                 O   s  ddl m}m} t|ƒdkr,tdt|ƒ ƒ‚t|d ƒ}t|d ƒ}t||tfƒ�r>t||tfƒ�r>| ¡ \}}| ¡ \}	}
t|ƒdks–t|d |ƒs¦t	dt|Ž  ƒ‚t|
ƒdksÀt|
d |ƒsÐt	dt|
Ž  ƒ‚|d  
¡ |
d jk�st	d|d j|
d jf ƒ‚tj| f|d |
d fž|Ž}|d j|_t||	 Ž | S g }t|tƒ�rŒt|tƒ�rŒ|jD ](}|jD ]}| t||f|Ž¡ �qj�q`npt|tƒ�r¼|jD ]}| t||f|Ž¡ �qžn@t|tƒ�rì|jD ]}| t||f|Ž¡ �qÎnt	d	||f ƒ‚t|Ž S )
Nr   )ÚKetBaseÚBraBaserb   z2 parameters expected, got %dr)   z"KetBase subclass expected, got: %rz"BraBase subclass expected, got: %rz(ket and bra are not dual classes: %r, %rz,Expected ket and bra expression, got: %r, %r)Úsympy.physics.quantum.stateri   rj   r+   r^   r   rN   r   Zargs_cncÚ	TypeErrorZ
dual_classr"   r   Ú__new__Zhilbert_spacer   r&   Úappendr   )Úclsr&   Zold_assumptionsri   rj   Zket_exprZbra_exprZket_cZketsZbra_cZbrasÚobjZop_termsZket_termZbra_termr   r   r   rm   ”  sd    ÿÿÿÿÿ

ÿ
ÿ
ÿÿÿzOuterProduct.__new__c                 C   s
   | j d S )z5Return the ket on the left side of the outer product.r   ©r&   r   r   r   r   rC   Ì  s    zOuterProduct.ketc                 C   s
   | j d S )z6Return the bra on the right side of the outer product.r)   rq   r   r   r   r   rE   Ñ  s    zOuterProduct.brac                 C   s   t t| jƒt| jƒƒS r!   )r   r   rE   rC   r   r   r   r   r[   Ö  s    zOuterProduct._eval_adjointc                 G   s   |  | j¡|  | j¡ S r!   ©Ú_printrC   rE   r$   r   r   r   Ú	_sympystrÙ  s    zOuterProduct._sympystrc                 G   s.   d| j j|j| jf|žŽ |j| jf|žŽ f S )Nz	%s(%s,%s))r"   r#   rs   rC   rE   r$   r   r   r   Ú
_sympyreprÜ  s     ÿzOuterProduct._sympyreprc                 G   s.   | j j|f|žŽ }t| | jj|f|žŽ ¡Ž S r!   )rC   Ú_prettyr   r3   rE   )r   r%   r&   r7   r   r   r   rv   à  s    zOuterProduct._prettyc                 G   s,   |j | jf|žŽ }|j | jf|žŽ }|| S r!   rr   )r   r%   r&   ÚkÚbr   r   r   Ú_latexä  s    zOuterProduct._latexc                 K   s$   | j jf |Ž}| jjf |Ž}|| S r!   )rC   Ú
_representrE   )r   r?   rw   rx   r   r   r   rz   é  s    zOuterProduct._representc                 K   s   | j j| jf|ŽS r!   )rC   Ú_eval_tracerE   )r   Úkwargsr   r   r   r{   î  s    zOuterProduct._eval_traceN)r#   rQ   rR   rS   Zis_commutativerm   rh   rC   rE   r[   rt   ru   rv   ry   rz   r{   r   r   r   r   r   U  s   <8

c                   @   s`   e Zd ZdZedd„ ƒZedd„ ƒZedd„ ƒZedd	„ ƒZd
d„ Z	dd„ Z
dd„ Zdd„ ZdS )r   a+  An operator for representing the differential operator, i.e. d/dx

    It is initialized by passing two arguments. The first is an arbitrary
    expression that involves a function, such as ``Derivative(f(x), x)``. The
    second is the function (e.g. ``f(x)``) which we are to replace with the
    ``Wavefunction`` that this ``DifferentialOperator`` is applied to.

    Parameters
    ==========

    expr : Expr
           The arbitrary expression which the appropriate Wavefunction is to be
           substituted into

    func : Expr
           A function (e.g. f(x)) which is to be replaced with the appropriate
           Wavefunction when this DifferentialOperator is applied

    Examples
    ========

    You can define a completely arbitrary expression and specify where the
    Wavefunction is to be substituted

    >>> from sympy import Derivative, Function, Symbol
    >>> from sympy.physics.quantum.operator import DifferentialOperator
    >>> from sympy.physics.quantum.state import Wavefunction
    >>> from sympy.physics.quantum.qapply import qapply
    >>> f = Function('f')
    >>> x = Symbol('x')
    >>> d = DifferentialOperator(1/x*Derivative(f(x), x), f(x))
    >>> w = Wavefunction(x**2, x)
    >>> d.function
    f(x)
    >>> d.variables
    (x,)
    >>> qapply(d*w)
    Wavefunction(2, x)

    c                 C   s   | j d j S )a�  
        Returns the variables with which the function in the specified
        arbitrary expression is evaluated

        Examples
        ========

        >>> from sympy.physics.quantum.operator import DifferentialOperator
        >>> from sympy import Symbol, Function, Derivative
        >>> x = Symbol('x')
        >>> f = Function('f')
        >>> d = DifferentialOperator(1/x*Derivative(f(x), x), f(x))
        >>> d.variables
        (x,)
        >>> y = Symbol('y')
        >>> d = DifferentialOperator(Derivative(f(x, y), x) +
        ...                          Derivative(f(x, y), y), f(x, y))
        >>> d.variables
        (x, y)
        rM   rq   r   r   r   r   Ú	variables  s    zDifferentialOperator.variablesc                 C   s
   | j d S )ad  
        Returns the function which is to be replaced with the Wavefunction

        Examples
        ========

        >>> from sympy.physics.quantum.operator import DifferentialOperator
        >>> from sympy import Function, Symbol, Derivative
        >>> x = Symbol('x')
        >>> f = Function('f')
        >>> d = DifferentialOperator(Derivative(f(x), x), f(x))
        >>> d.function
        f(x)
        >>> y = Symbol('y')
        >>> d = DifferentialOperator(Derivative(f(x, y), x) +
        ...                          Derivative(f(x, y), y), f(x, y))
        >>> d.function
        f(x, y)
        rM   rq   r   r   r   r   Úfunction8  s    zDifferentialOperator.functionc                 C   s
   | j d S )a¯  
        Returns the arbitrary expression which is to have the Wavefunction
        substituted into it

        Examples
        ========

        >>> from sympy.physics.quantum.operator import DifferentialOperator
        >>> from sympy import Function, Symbol, Derivative
        >>> x = Symbol('x')
        >>> f = Function('f')
        >>> d = DifferentialOperator(Derivative(f(x), x), f(x))
        >>> d.expr
        Derivative(f(x), x)
        >>> y = Symbol('y')
        >>> d = DifferentialOperator(Derivative(f(x, y), x) +
        ...                          Derivative(f(x, y), y), f(x, y))
        >>> d.expr
        Derivative(f(x, y), x) + Derivative(f(x, y), y)
        r   rq   r   r   r   r   ÚexprP  s    zDifferentialOperator.exprc                 C   s   | j jS )z<
        Return the free symbols of the expression.
        )r   Úfree_symbolsr   r   r   r   r€   i  s    z!DifferentialOperator.free_symbolsc                 K   sN   ddl m} | j}|jdd … }| j}| j |||Ž ¡}| ¡ }||f|žŽ S )Nr   )ÚWavefunctionr)   )rk   r�   r}   r&   r~   r   ÚsubsZdoit)r   Úfuncr?   r�   ÚvarZwf_varsÚfÚnew_exprr   r   r   Ú_apply_operator_Wavefunctionq  s    z1DifferentialOperator._apply_operator_Wavefunctionc                 C   s   t | j|ƒ}t|| jd ƒS rL   )r   r   r   r&   )r   Úsymbolr†   r   r   r   Ú_eval_derivative|  s    z%DifferentialOperator._eval_derivativec                 G   s$   d| j |f|žŽ | j|f|žŽ f S )Nr*   )r'   r-   r$   r   r   r   rs   „  s    þzDifferentialOperator._printc                 G   sD   | j |f|žŽ }| j|f|žŽ }t|jddd�Ž }t| |¡Ž }|S )Nr/   r0   r1   )r(   r4   r   r5   r3   r6   r   r   r   Ú_print_prettyŠ  s    ÿz"DifferentialOperator._print_prettyN)r#   rQ   rR   rS   rh   r}   r~   r   r€   r‡   r‰   rs   rŠ   r   r   r   r   r   õ  s   )



N) rS   Útypingr   Zsympy.core.addr   Zsympy.core.exprr   Zsympy.core.functionr   r   Zsympy.core.mulr   Zsympy.core.numbersr	   rX   r   Z sympy.printing.pretty.stringpictr   Zsympy.physics.quantum.daggerr   Zsympy.physics.quantum.qexprr   r   Zsympy.matricesr   Ú__all__r   r   r   r   r   r   r   r   r   r   Ú<module>   s4   
ú 'T !