o
    3Ih*                     @   sN  d 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lmZ dd	lmZmZmZ dd
lmZmZmZ ddlmZmZmZ ddlmZ e
dZ	 eeedd Z ej!eefdd ed ej!eefdd ed ej!eefdd ed eeedd Z"eeedd Z#eeedd Z$eeedd Z%eeedd Z&eeedd  Z'eeed!d" Z(eeed#d$ Z)eeed%d& Z*eeed'd( Z+eeed)d* Z,eeed+d, Z-d-d. Z.d/d0 Z/d1d2 Z0e.ge/gd3ej1e< e.ge0gd3ej1e< d4e.giej1e< d5S )6a)  Transforms that are always applied to quantum expressions.

This module uses the kind and _constructor_postprocessor_mapping APIs
to transform different combinations of Operators, Bras, and Kets into
Inner/Outer/TensorProducts. These transformations are registered
with the postprocessing API of core classes like `Mul` and `Pow` and
are always applied to any expression involving Bras, Kets, and
Operators. This API replaces the custom `__mul__` and `__pow__`
methods of the quantum classes, which were found to be inconsistent.

THIS IS EXPERIMENTAL.
    )Basic)Expr)Mul)S)
Dispatcher#ambiguity_register_error_ignore_dup)debugInnerProduct)KetKindBraKindOperatorKind)OuterProductIdentityOperatorOperator)BraBaseKetBase	StateBase)TensorProduct_transform_state_pairc                 C   s   dS )z5Default transformer that does nothing for base types.N abr   r   `/home/air/sanwanet/gpt-api/venv/lib/python3.10/site-packages/sympy/physics/quantum/transforms.py_transform_expr7   s   r   c                 C   s   |fS Nr   xyr   r   r   <lambda>@       r    )on_ambiguityc                 C   s   | fS r   r   r   r   r   r   r    E   r!   c                 C   s   t jS r   )r   Oner   r   r   r   r    J   r!   c                 C      t | |fS )z.Transform a bra*ket -> InnerProduct(bra, ket).r	   r   r   r   r   _transform_bra_ketN      r%   c                 C   r$   )z.Transform a keT*bra -> OuterProduct(ket, bra).)r   r   r   r   r   _transform_ket_braS   r&   r'   c                 C      t d)zRaise a TypeError if a user tries to multiply two kets.

    Multiplication based on `*` is not a shorthand for tensor products.
    zEMultiplication of two kets is not allowed. Use TensorProduct instead.	TypeErrorr   r   r   r   _transform_ket_ketX      r+   c                 C   r(   )zRaise a TypeError if a user tries to multiply two bras.

    Multiplication based on `*` is not a shorthand for tensor products.
    zEMultiplication of two bras is not allowed. Use TensorProduct instead.r)   r   r   r   r   _transform_bra_brab   r,   r-   c                 C   s   t | j|| jfS r   )r
   braketr   r   r   r   _transform_op_ketl      r0   c                 C   s   t | |j|jfS r   )r
   r/   r.   r   r   r   r   _transform_bra_opp   r1   r2   c                 C      | j tkr	tddS )zRaise a TypeError if a user tries to multiply TensorProduct(*kets)*ket.

    Multiplication based on `*` is not a shorthand for tensor products.
    z6Multiplication of TensorProduct(*kets)*ket is invalid.Nkindr   r*   r   r   r   r   _transform_tp_kett   
   
r6   c                 C      |j tkr	tddS )zRaise a TypeError if a user tries to multiply ket*TensorProduct(*kets).

    Multiplication based on `*` is not a shorthand for tensor products.
    z6Multiplication of ket*TensorProduct(*kets) is invalid.Nr4   r   r   r   r   _transform_ket_tp   r7   r9   c                 C   r3   )zRaise a TypeError if a user tries to multiply TensorProduct(*bras)*bra.

    Multiplication based on `*` is not a shorthand for tensor products.
    z6Multiplication of TensorProduct(*bras)*bra is invalid.Nr5   r   r*   r   r   r   r   _transform_tp_bra   r7   r;   c                 C   r8   )zRaise a TypeError if a user tries to multiply bra*TensorProduct(*bras).

    Multiplication based on `*` is not a shorthand for tensor products.
    z6Multiplication of bra*TensorProduct(*bras) is invalid.Nr:   r   r   r   r   _transform_bra_tp   r7   r<   c                 C   sr   t d| | t| jt|jkr7| jtkr(|jtkr(tdd t| j|jD S tdd t| j|jD  fS dS )zECombine a product of tensor products if their number of args matches._transform_tp_tpc                 S   s   g | ]	\}}t ||qS r   r	   .0ijr   r   r   
<listcomp>   s    z$_transform_tp_tp.<locals>.<listcomp>c                 s   s    | ]	\}}|| V  qd S r   r   r>   r   r   r   	<genexpr>   s    z#_transform_tp_tp.<locals>.<genexpr>N)	r   lenargsr5   r   r   tuplezipr   r   r   r   r   r=      s   r=   c                 C   s   t | j|jt| j|jfS )z9Extract an inner produt from a product of outer products.)r
   r.   r/   r   r   r   r   r   _transform_op_op   s   rH   c                 C   s   t | j}g }t|dkrA|d}|d }t||}|du r%|| n|d |d|d  ||dd  t|dks|rJ||d  tj	|ddS )a  Transform a ``Mul`` of quantum expressions into canonical form.

    This function is registered ``_constructor_postprocessor_mapping`` as a
    transformer for ``Mul``. This means that every time a quantum expression
    is multiplied, this function will be called to transform it into canonical
    form as defined by the binary functions registered with
    ``_transform_state_pair``.

    The algorithm of this function is as follows. It walks the args
    of the input ``Mul`` from left to right and calls ``_transform_state_pair``
    on every overlapping pair of args. Each time ``_transform_state_pair``
    is called it can return a tuple of items or None. If None, the pair isn't
    transformed. If a tuple, then the last element of the tuple goes back into
    the args to be transformed again and the others are extended onto the result
    args list.

    The algorithm can be visualized in the following table:

    step   result                                 args
    ============================================================================
    #0     []                                     [a, b, c, d, e, f]
    #1     []                                     [T(a,b), c, d, e, f]
    #2     [T(a,b)[:-1]]                          [T(a,b)[-1], c, d, e, f]
    #3     [T(a,b)[:-1]]                          [T(T(a,b)[-1], c), d, e, f]
    #4     [T(a,b)[:-1], T(T(a,b)[-1], c)[:-1]]   [T(T(T(a,b)[-1], c)[-1], d), e, f]
    #5     ...

    One limitation of the current implementation is that we assume that only the
    last item of the transformed tuple goes back into the args to be transformed
    again. These seems to handle the cases needed for Mul. However, we may need
    to extend the algorithm to have the entire tuple go back into the args for
    further transformation.
       r   NF)is_commutative)
listrE   rD   popr   appendinsertextendr   
_from_args)exprrE   resultfirstsecondtransformedr   r   r   _postprocess_state_mul   s   
"


rW   c                 C   s,   |   \}}|jtks|jtkrtddS )zHandle bras and kets raised to powers.

    Under ``*`` multiplication this is invalid. Users should use a
    TensorProduct instead.
    z>A bra or ket to a power is invalid, use TensorProduct instead.N)as_base_expr5   r   r   r*   )rR   baseexpr   r   r   _postprocess_state_pow   s   r[   c                    sh   |   \} td| | j t|tr, jr. jr0|jtkr2 fdd|jD }t| S dS dS dS dS )a  Handle TensorProduct(*operators)**(positive integer).

    This handles a tensor product of operators, to an integer power.
    The power here is interpreted as regular multiplication, not
    tensor product exponentiation. The form of exponentiation performed
    here leaves the space and dimension of the object the same.

    This operation does not make sense for tensor product's of states.
    z_postprocess_tp_pow: c                    s   g | ]}|  qS r   r   )r?   r   rZ   r   r   rB     s    z'_postprocess_tp_pow.<locals>.<listcomp>N)	rX   r   rE   
isinstancer   
is_integeris_positiver5   r   )rR   rY   new_argsr   r\   r   _postprocess_tp_pow  s   
 ra   )r   Powr   N)2__doc__sympy.core.basicr   sympy.core.exprr   sympy.core.mulr   sympy.core.singletonr   !sympy.multipledispatch.dispatcherr   r   sympy.utilities.miscr   "sympy.physics.quantum.innerproductr
   sympy.physics.quantum.kindr   r   r   sympy.physics.quantum.operatorr   r   r   sympy.physics.quantum.stater   r   r   #sympy.physics.quantum.tensorproductr   r   registerr   addr%   r'   r+   r-   r0   r2   r6   r9   r;   r<   r=   rH   rW   r[   ra   "_constructor_postprocessor_mappingr   r   r   r   <module>   s    








	

	

















	

?