Ë
    �\;jh  ã                   óR   — d dl Z d dlmZmZ d dlmZ g Zej                  dd„«       Zy)é    N)ÚcoreÚ	framework)Úgradients_with_optimizerc                 óø  — d„ } || d«      } t        | «      t        t        | «      «      k(  sJ d«       ‚|�_t        |t        t        f«      s|g}|D ]@  }|€Œt        |t
        j                  t        j                  j                  f«      rŒ;J d«       ‚ ng }t        |«      dkD  rt        | «      t        |«      k(  sJ d«       ‚t        |t        «      sJ d«       ‚t        j                  j                  | ||«       y)	a		  
    Compute the backward gradients of given tensors.

    Args:
        tensors(list of Tensors): the tensors which the gradient to be computed. The tensors can not contain the same tensor.

        grad_tensors(list of Tensors of None, optional): the init gradients of the `tensors`` .If not None, it must have the same length with ``tensors`` ,
            and if any of the elements is None, then the init gradient is the default value which is filled with 1.0.
            If None, all the gradients of the ``tensors`` is the default value which is filled with 1.0.
            Defaults to None.

        retain_graph(bool, optional): If False, the graph used to compute grads will be freed. If you would
            like to add more ops to the built graph after calling this method( :code:`backward` ), set the parameter
            :code:`retain_graph` to True, then the grads will be retained. Thus, setting it to False is much more memory-efficient.
            Defaults to False.

    Returns:
        NoneType: None


    Examples:
        .. code-block:: python

            >>> import paddle
            >>> x = paddle.to_tensor([[1, 2], [3, 4]], dtype='float32', stop_gradient=False)
            >>> y = paddle.to_tensor([[3, 2], [3, 4]], dtype='float32')

            >>> grad_tensor1 = paddle.to_tensor([[1,2], [2, 3]], dtype='float32')
            >>> grad_tensor2 = paddle.to_tensor([[1,1], [1, 1]], dtype='float32')

            >>> z1 = paddle.matmul(x, y)
            >>> z2 = paddle.matmul(x, y)

            >>> paddle.autograd.backward([z1, z2], [grad_tensor1, grad_tensor2], True)
            >>> print(x.grad)
            Tensor(shape=[2, 2], dtype=float32, place=Place(cpu), stop_gradient=False,
            [[12., 18.],
             [17., 25.]])


            >>> x.clear_grad()

            >>> paddle.autograd.backward([z1, z2], [grad_tensor1, None], True)
            >>> print(x.grad)
            Tensor(shape=[2, 2], dtype=float32, place=Place(cpu), stop_gradient=False,
            [[12., 18.],
             [17., 25.]])

            >>> x.clear_grad()

            >>> paddle.autograd.backward([z1, z2])
            >>> print(x.grad)
            Tensor(shape=[2, 2], dtype=float32, place=Place(cpu), stop_gradient=False,
            [[10., 14.],
             [10., 14.]])


    c                 óˆ  — | €
J |› d�«       ‚t        | t        t        f«      r`t        | «      dkD  s
J |› d�«       ‚| D ]A  }t        |t        j
                  t        j                  j
                  f«      rŒ8J d|› d�«       ‚ | S t        | t        j
                  t        j                  j
                  f«      s
J |› d�«       ‚| gS )Nz should not be Noner   z connot be emptyzElements of z must be paddle.Tensorz! must be Tensor or list of Tensor)Ú
isinstanceÚlistÚtupleÚlenÚpaddleÚTensorr   Úeager)Úin_out_listÚnameÚeach_vars      úfG:\00. PROJECTS\API\Inventory\templateJSON\kerjaOCR\Lib\site-packages\paddle/autograd/backward_mode.pyÚcheck_tensorszbackward.<locals>.check_tensorsS   sÛ   € ØÐ&ÐD¨4¨&Ð0CÐ(DÓDÐ&ä�k¤D¬% =Ô1Ü�{Ó# aÒ'ÐB¨D¨6Ð1AÐ)BÓBÐ'Û'�Ü!ØœvŸ}™}¬d¯j©j×.?Ñ.?Ð@õð ?à! $ Ð'=Ð>ó?ð ð (ð ÐäØœfŸm™m¬T¯Z©Z×->Ñ->Ð?ôð :à�Ð8Ð9ó:ð ð  �=Ð ó    Útensorsz[The argument 'tensors' of paddle.autograd.backward contains duplicate paddle.Tensor object.Nz„The argument 'grad_tensors' of paddle.autograd.backward is invalid, it can be 'None', 'paddle.Tensor' or 'list[None/paddle.Tensor]'.r   z3The length of grad_tensors must be equal to tensorsz"retain_graph must be True or False)r   Úsetr   r	   r
   r   r   r   r   ÚboolÚrun_backward)r   Úgrad_tensorsÚretain_graphr   Úeach_tensors        r   Úbackwardr      s  € òz!ñ  ˜G YÓ/€Gäˆw‹<œ3ÜˆG‹óò ð eàdóeð ð ÐÜ˜,¬¬u¨Ô6Ø(˜>ˆLã'ˆKØÑ&Ü!Ø¤&§-¡-´·±×1BÑ1BÐ!Cõð Zð ZóZð ñ (ð ˆä
ˆ<Ó˜1ÒÜ�7‹|œsØó 
ò 
ð 	Aà@ó	Að 
ô �l¤DÔ)ÐOÐ+OÓOÐ)ä‡J�J×Ñ˜G \°<Õ@r   )NF)	r   Úpaddle.baser   r   Úpaddle.base.backwardr   Ú__all__Údygraph_onlyr   © r   r   Ú<module>r"      s3   ðó ß 'Ý 9à
€ð ×ÑòeAó ñeAr   