o
    h:                     @   s  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
 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 ddlmZ ddlmZmZ ddlmZm Z m!Z! ddl"m#Z# ddgZ$da%dd Z&G dd deZ'dd Z(dd Z)dd Z*dS )zAbstract tensor product.    )Add)Expr)Mul)Pow)sympify)DenseMatrix)ImmutableDenseMatrix)
prettyForm)QuantumErrorDagger)
Commutator)AntiCommutator)KetBra)numpy_ndarrayscipy_sparse_matrixmatrix_tensor_product)TrTensorProducttensor_product_simpFc                 C   s   | a dS )a  Set flag controlling whether tensor products of states should be
    printed as a combined bra/ket or as an explicit tensor product of different
    bra/kets. This is a global setting for all TensorProduct class instances.

    Parameters
    ----------
    combine : bool
        When true, tensor product states are combined into one ket/bra, and
        when false explicit tensor product notation is used between each
        ket/bra.
    N)_combined_printing)combined r   W/var/www/vscode/kcb/lib/python3.10/site-packages/sympy/physics/quantum/tensorproduct.pycombined_tensor_printing%   s   r   c                   @   sh   e Zd ZdZdZ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S )r   a  The tensor product of two or more arguments.

    For matrices, this uses ``matrix_tensor_product`` to compute the Kronecker
    or tensor product matrix. For other objects a symbolic ``TensorProduct``
    instance is returned. The tensor product is a non-commutative
    multiplication that is used primarily with operators and states in quantum
    mechanics.

    Currently, the tensor product distinguishes between commutative and
    non-commutative arguments.  Commutative arguments are assumed to be scalars
    and are pulled out in front of the ``TensorProduct``. Non-commutative
    arguments remain in the resulting ``TensorProduct``.

    Parameters
    ==========

    args : tuple
        A sequence of the objects to take the tensor product of.

    Examples
    ========

    Start with a simple tensor product of SymPy matrices::

        >>> from sympy import Matrix
        >>> from sympy.physics.quantum import TensorProduct

        >>> m1 = Matrix([[1,2],[3,4]])
        >>> m2 = Matrix([[1,0],[0,1]])
        >>> TensorProduct(m1, m2)
        Matrix([
        [1, 0, 2, 0],
        [0, 1, 0, 2],
        [3, 0, 4, 0],
        [0, 3, 0, 4]])
        >>> TensorProduct(m2, m1)
        Matrix([
        [1, 2, 0, 0],
        [3, 4, 0, 0],
        [0, 0, 1, 2],
        [0, 0, 3, 4]])

    We can also construct tensor products of non-commutative symbols:

        >>> from sympy import Symbol
        >>> A = Symbol('A',commutative=False)
        >>> B = Symbol('B',commutative=False)
        >>> tp = TensorProduct(A, B)
        >>> tp
        AxB

    We can take the dagger of a tensor product (note the order does NOT reverse
    like the dagger of a normal product):

        >>> from sympy.physics.quantum import Dagger
        >>> Dagger(tp)
        Dagger(A)xDagger(B)

    Expand can be used to distribute a tensor product across addition:

        >>> C = Symbol('C',commutative=False)
        >>> tp = TensorProduct(A+B,C)
        >>> tp
        (A + B)xC
        >>> tp.expand(tensorproduct=True)
        AxC + BxC
    Fc                 G   sz   t |d ttttfrt| S | t|\}}t| }t	|dkr$|S t	|dkr0||d  S t
j| g|R  }|| S )Nr      )
isinstanceMatrixImmutableMatrixr   r   r   flattenr   r   lenr   __new__)clsargsc_partnew_argstpr   r   r   r"   {   s   zTensorProduct.__new__c                 C   sD   g }g }|D ]}|  \}}|t| |t| q||fS N)args_cncextendlistappendr   
_from_args)r#   r$   r%   nc_partsargcpncpr   r   r   r       s   zTensorProduct.flattenc                 C   s   t dd | jD  S )Nc                 S      g | ]}t |qS r   r   ).0ir   r   r   
<listcomp>       z/TensorProduct._eval_adjoint.<locals>.<listcomp>r   r$   )selfr   r   r   _eval_adjoint      zTensorProduct._eval_adjointc                 K   s   t | jddS )NT)tensorproduct)r   expand)r8   ruler$   hintsr   r   r   _eval_rewrite   s   zTensorProduct._eval_rewritec                 G   s   t | j}d}t|D ]4}t| j| tttfr|d }||| j|  }t| j| tttfr5|d }||d kr?|d }q|S )N ()r   x)r!   r$   ranger   r   r   r   _print)r8   printerr$   lengthsr4   r   r   r   	_sympystr   s   
zTensorProduct._sympystrc           
      G   s  t rtdd | jD stdd | jD rt| j}|jdg|R  }t|D ]d}|jdg|R  }t| j| j}t|D ]%}|j| j| j| g|R  }	t||	 }||d krdt|d }q?t| j| jdkrxt|jddd	 }t|| }||d krt|d }q(t|	| jd
 j
 }t|| jd
 j }|S t| j}|jdg|R  }t|D ]@}|j| j| g|R  }t| j| ttfrt|jddd	 }t|| }||d kr|jrt|d }qt|d }q|S )Nc                 s       | ]}t |tV  qd S r(   r   r   r3   r/   r   r   r   	<genexpr>       z(TensorProduct._pretty.<locals>.<genexpr>c                 s   rJ   r(   r   r   rL   r   r   r   rM      rN   r@   r   , {})leftrightr   rA   rB   u   ⨂ zx )r   allr$   r!   rE   rD   r	   rT   parensrS   lbracketrbracketr   r   r   _use_unicode)
r8   rF   r$   rG   pformr4   
next_pformlength_ij
part_pformr   r   r   _pretty   sT   

zTensorProduct._prettyc                    s   t r8tdd | jD stdd | jD r8dd  d fdd| jD }d	| jd
 j|| jd
 jf S t| j}d}t|D ]:}t| j| t	t
frS|d }|d j| j| gR   d }t| j| t	t
frs|d }||d kr}|d }qC|S )Nc                 s   rJ   r(   rK   rL   r   r   r   rM      rN   z'TensorProduct._latex.<locals>.<genexpr>c                 s   rJ   r(   rO   rL   r   r   r   rM      rN   c                 S   s   |dkr| S d|  S )Nr   z\left\{%s\right\}r   )labelnlabelsr   r   r   _label_wrap   r:   z)TensorProduct._latex.<locals>._label_wraprP   c                    s*   g | ]} |j gR  t|jqS r   )_print_label_latexr!   r$   rL   rb   r$   rF   r   r   r5      s
    z(TensorProduct._latex.<locals>.<listcomp>z{%s%s%s}r   r@   z\left(rQ   rR   z\right)r   z\otimes )r   rU   r$   joinlbracket_latexrbracket_latexr!   rD   r   r   r   rE   )r8   rF   r$   rH   rG   r4   r   rd   r   _latex   s0   

$zTensorProduct._latexc                    s   t  fdd| jD  S )Nc                    s   g | ]
}|j d i  qS )r   )doit)r3   itemr>   r   r   r5      s    z&TensorProduct.doit.<locals>.<listcomp>r7   )r8   r>   r   rk   r   ri      s   zTensorProduct.doitc           	      K   s   | j }g }tt|D ]K}t|| trV|| j D ]:}t|d| |f ||d d   }| \}}t|dkrHt|d trH|d  f}|t	| t	|   q nq|r]t| S | S )z*Distribute TensorProducts across addition.Nr   r   )
r$   rD   r!   r   r   r   r)   _eval_expand_tensorproductr,   r   )	r8   r>   r$   add_argsr4   aar'   r%   nc_partr   r   r   rl      s   &z(TensorProduct._eval_expand_tensorproductc                    sX   | dd  t| } d u st dkrtdd |jD  S t fddt|jD  S )Nindicesr   c                 S   s   g | ]}t | qS r   r   ri   rL   r   r   r   r5     s    z-TensorProduct._eval_trace.<locals>.<listcomp>c                    s(   g | ]\}}| v rt | n|qS r   rq   )r3   idxvaluerp   r   r   r5     s    )getr   r!   r   r$   	enumerate)r8   kwargsexpr   rt   r   _eval_trace  s   zTensorProduct._eval_traceN)__name__
__module____qualname____doc__is_commutativer"   classmethodr    r9   r?   rI   r_   rh   ri   rl   ry   r   r   r   r   r   5   s    C

,c           
      C   s  t | ts| S |  \}}t|}|dkr| S |dkr.t |d tr,t| t|d  S | S | tr|d }t |tsRt |trLt |jtrKt|}nt	d| t|j
}t|j
}|dd D ]]}t |tr|t|j
krxtd||f tt|D ]}|| |j
|  ||< q~n0t |trt |jtrt|}	tt|D ]}|| |	j
|  ||< qnt	d| t	d| |}qbt| t|  S | trdd |D }tt| t|  S | S )at  Simplify a Mul with TensorProducts.

    Current the main use of this is to simplify a ``Mul`` of ``TensorProduct``s
    to a ``TensorProduct`` of ``Muls``. It currently only works for relatively
    simple cases where the initial ``Mul`` only has scalars and raw
    ``TensorProduct``s, not ``Add``, ``Pow``, ``Commutator``s of
    ``TensorProduct``s.

    Parameters
    ==========

    e : Expr
        A ``Mul`` of ``TensorProduct``s to be simplified.

    Returns
    =======

    e : Expr
        A ``TensorProduct`` of ``Mul``s.

    Examples
    ========

    This is an example of the type of simplification that this function
    performs::

        >>> from sympy.physics.quantum.tensorproduct import                     tensor_product_simp_Mul, TensorProduct
        >>> from sympy import Symbol
        >>> A = Symbol('A',commutative=False)
        >>> B = Symbol('B',commutative=False)
        >>> C = Symbol('C',commutative=False)
        >>> D = Symbol('D',commutative=False)
        >>> e = TensorProduct(A,B)*TensorProduct(C,D)
        >>> e
        AxB*CxD
        >>> tensor_product_simp_Mul(e)
        (A*C)x(B*D)

    r   r   zTensorProduct expected, got: %rNz.TensorProducts of different lengths: %r and %rc                 S   r2   r   )tensor_product_simp_Pow)r3   ncr   r   r   r5   j  r6   z+tensor_product_simp_Mul.<locals>.<listcomp>)r   r   r)   r!   r   r   hasr   base	TypeErrorr$   r+   r
   rD   tensor_product_simp_Mul)
er%   ro   n_nccurrentn_termsr&   nextr4   new_tpr   r   r   r     sZ   
,







r   c                    s8   t  ts S t  jtrt fdd jjD  S  S )z=Evaluates ``Pow`` expressions whose base is ``TensorProduct``c                    s   g | ]}| j  qS r   )rx   )r3   br   r   r   r5   u  s    z+tensor_product_simp_Pow.<locals>.<listcomp>)r   r   r   r   r$   r   r   r   r   r   o  s
   
r   c                 K   s   t | trtdd | jD  S t | tr&t | jtrt| S t| j| j S t | t	r/t
| S t | tr>tdd | jD  S t | trMtdd | jD  S | S )a3  Try to simplify and combine TensorProducts.

    In general this will try to pull expressions inside of ``TensorProducts``.
    It currently only works for relatively simple cases where the products have
    only scalars, raw ``TensorProducts``, not ``Add``, ``Pow``, ``Commutators``
    of ``TensorProducts``. It is best to see what it does by showing examples.

    Examples
    ========

    >>> from sympy.physics.quantum import tensor_product_simp
    >>> from sympy.physics.quantum import TensorProduct
    >>> from sympy import Symbol
    >>> A = Symbol('A',commutative=False)
    >>> B = Symbol('B',commutative=False)
    >>> C = Symbol('C',commutative=False)
    >>> D = Symbol('D',commutative=False)

    First see what happens to products of tensor products:

    >>> e = TensorProduct(A,B)*TensorProduct(C,D)
    >>> e
    AxB*CxD
    >>> tensor_product_simp(e)
    (A*C)x(B*D)

    This is the core logic of this function, and it works inside, powers, sums,
    commutators and anticommutators as well:

    >>> tensor_product_simp(e**2)
    (A*C)x(B*D)**2

    c                 S   r2   r   r   rL   r   r   r   r5     r6   z'tensor_product_simp.<locals>.<listcomp>c                 S   r2   r   r   rL   r   r   r   r5     r6   c                 S   r2   r   r   rL   r   r   r   r5     r6   )r   r   r$   r   r   r   r   r   rx   r   r   r   r   )r   r>   r   r   r   r   y  s   
"



N)+r}   sympy.core.addr   sympy.core.exprr   sympy.core.mulr   sympy.core.powerr   sympy.core.sympifyr   sympy.matrices.denser   r   sympy.matrices.immutabler   r    sympy.printing.pretty.stringpictr	   sympy.physics.quantum.qexprr
   sympy.physics.quantum.daggerr    sympy.physics.quantum.commutatorr   $sympy.physics.quantum.anticommutatorr   sympy.physics.quantum.stater   r   !sympy.physics.quantum.matrixutilsr   r   r   sympy.physics.quantum.tracer   __all__r   r   r   r   r   r   r   r   r   r   <module>   s4    	 _\
