U
    	-eoK                     @   s   d 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.
    )Add)Expr)
Derivativeexpand)MulooS
prettyForm)Dagger)QExprdispatch_method)eyeOperatorHermitianOperatorUnitaryOperatorIdentityOperatorOuterProductDifferentialOperatorc                   @   s   e Zd ZdZ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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
    c                 C   s   dS )N)O selfr   r   _/var/www/html/Darija-Ai-Train/env/lib/python3.8/site-packages/sympy/physics/quantum/operator.pydefault_argsh   s    zOperator.default_args,c                 G   s   | j jS N)	__class____name__r   printerargsr   r   r   _print_operator_namer   s    zOperator._print_operator_namec                 G   s   t | jjS r   )r   r   r    r!   r   r   r   _print_operator_name_prettyw   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_contentsz   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   parensr0   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   r8      s    zOperator._eval_commutatorc                 K   s   t | d|f|S )z Evaluate [self, other] if known._eval_anticommutatorr9   r:   r   r   r   r=      s    zOperator._eval_anticommutatorc                 K   s   t | d|f|S )N_apply_operatorr9   r   ketr<   r   r   r   r>      s    zOperator._apply_operatorc                 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 Nr   r   r   r   r   rD      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__N)r    
__module____qualname____doc__classmethodr   Z_label_separatorr$   r6   r%   r+   r5   r7   r8   r=   r>   rB   rE   invrD   rJ   r   r   r   r   r   %   s$   B
	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   )rH   r   r   rD   r   r   r   r   rD      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	   )	rH   r   Zis_evensympy.core.singletonr
   ZOneZis_oddr   _eval_power)r   expr
   r   r   r   rQ      s    
zHermitianOperator._eval_powerN)r    rK   rL   rM   Zis_hermitianrD   rQ   r   r   r   r   r      s   c                   @   s   e 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
    c                 C   s   |   S r   rC   r   r   r   r   _eval_adjoint   s    zUnitaryOperator._eval_adjointN)r    rK   rL   rM   rS   r   r   r   r   r      s   c                   @   s   e 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
    c                 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   rT   )r   r#   hintsr   r   r   __init__  s    zIdentityOperator.__init__c                 K   s   t jS r   )r
   ZZeror   r;   rW   r   r   r   r8     s    z!IdentityOperator._eval_commutatorc                 K   s   d| S )N   r   rY   r   r   r   r=     s    z%IdentityOperator._eval_anticommutatorc                 C   s   | S r   r   r   r   r   r   rD   "  s    zIdentityOperator._eval_inversec                 C   s   | S r   r   r   r   r   r   rS   %  s    zIdentityOperator._eval_adjointc                 K   s   |S r   r   r?   r   r   r   r>   (  s    z IdentityOperator._apply_operatorc                 K   s   |S r   r   )r   brar<   r   r   r   _apply_from_right_to+  s    z%IdentityOperator._apply_from_right_toc                 C   s   | S r   r   )r   rR   r   r   r   rQ   .  s    zIdentityOperator._eval_powerc                 G   s   dS NIr   r!   r   r   r   r+   1  s    z IdentityOperator._print_contentsc                 G   s   t dS r]   r   r!   r   r   r   r5   4  s    z'IdentityOperator._print_contents_prettyc                 G   s   dS )Nz{\mathcal{I}}r   r!   r   r   r   r7   7  s    z&IdentityOperator._print_contents_latexc                 C   s   t |ttfr|S t| |S r   )rH   r   r   r   rI   r   r   r   rJ   :  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.)rT   r   rA   getr   )r   r<   r_   r   r   r   _represent_default_basisA  s    z)IdentityOperator._represent_default_basisN)r    rK   rL   rM   propertyrU   rN   r   rX   r8   r=   rD   rS   r>   r\   rQ   r+   r5   r7   rJ   ra   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st|d |st	dt|  t|
dkst|
d |st	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rt|tr|jD ](}|jD ]}|t||f| qjq`npt|tr|jD ]}|t||f| qn@t|tr|jD ]}|t||f| qnt	d	||f t| S )
Nr   )KetBaseBraBaserZ   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.staterc   rd   r(   rV   r   rH   r   Zargs_cnc	TypeErrorZ
dual_classr   r   __new__Zhilbert_spacer   r#   appendr   )clsr#   Zold_assumptionsrc   rd   Zket_exprZbra_exprZket_cZketsZbra_cZbrasobjZop_termsZket_termZbra_termr   r   r   rg     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   r@     s    zOuterProduct.ketc                 C   s
   | j d S )z6Return the bra on the right side of the outer product.r&   rk   r   r   r   r   r[     s    zOuterProduct.brac                 C   s   t t| jt| jS r   )r   r   r[   r@   r   r   r   r   rS     s    zOuterProduct._eval_adjointc                 G   s   | | j| | j S r   _printr@   r[   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    rm   r@   r[   r!   r   r   r   
_sympyrepr  s     zOuterProduct._sympyreprc                 G   s.   | j j|f| }t|| jj|f|  S r   )r@   _prettyr   r0   r[   )r   r"   r#   r4   r   r   r   rp     s    zOuterProduct._prettyc                 G   s,   |j | jf| }|j | jf| }|| S r   rl   )r   r"   r#   kbr   r   r   _latex  s    zOuterProduct._latexc                 K   s$   | j jf |}| jjf |}|| S r   )r@   
_representr[   )r   r<   rq   rr   r   r   r   rt     s    zOuterProduct._representc                 K   s   | j j| jf|S r   )r@   _eval_tracer[   )r   kwargsr   r   r   ru     s    zOuterProduct._eval_traceN)r    rK   rL   rM   Zis_commutativerg   rb   r@   r[   rS   rn   ro   rp   rs   rt   ru   r   r   r   r   r   N  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)
        rG   rk   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)
        rG   rk   r   r   r   r   function1  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   rk   r   r   r   r   exprI  s    zDifferentialOperator.exprc                 C   s   | j jS )z<
        Return the free symbols of the expression.
        )ry   free_symbolsr   r   r   r   rz   b  s    z!DifferentialOperator.free_symbolsc                 K   sN   ddl m} | j}|jdd  }| j}| j||| }| }||f| S )Nr   )Wavefunctionr&   )re   r{   rw   r#   rx   ry   subsZdoit)r   funcr<   r{   varZwf_varsfnew_exprr   r   r   _apply_operator_Wavefunctionj  s    z1DifferentialOperator._apply_operator_Wavefunctionc                 C   s   t | j|}t|| jd S rF   )r   ry   r   r#   )r   symbolr   r   r   r   _eval_derivativeu  s    z%DifferentialOperator._eval_derivativec                 G   s$   d| j |f| | j|f| f S )Nr'   )r$   r*   r!   r   r   r   rm   }  s    zDifferentialOperator._printc                 G   sD   | j |f| }| j|f| }t|jddd }t|| }|S )Nr,   r-   r.   )r%   r1   r   r2   r0   r3   r   r   r   _print_pretty  s    z"DifferentialOperator._print_prettyN)r    rK   rL   rM   rb   rw   rx   ry   rz   r   r   rm   r   r   r   r   r   r     s   )



N)rM   Zsympy.core.addr   Zsympy.core.exprr   Zsympy.core.functionr   r   Zsympy.core.mulr   Zsympy.core.numbersr   rP   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>   s2    'R !