o
    ®?e4  ć                   @   st  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	 e 
d	” e 
d
” e d”dd Ze d”dd Ze d”dd Ze d”dd Ze d”dd Ze d”dd Ze d”dd Zd d! Ze d"”d#d$ Ze d%”d&d' Ze d(”d)d* Ze d+”d,d- Ze d.”d/d0 Ze d1”d2d3 Ze d4”d5d6 Zd7S )8z1Gradients for operators defined in sparse_ops.py.é    )Śdtypes)Śops)Śsparse_tensor)Ś	array_ops)Śgen_sparse_ops)Śmath_ops)Ś
sparse_opsZSparseAddGradZSparseConcatZSparseReorderc           
      C   sb   | j d }| j d }t |”d }t |”}t |||”}t |”}t 	|j
”}	dt ||	”dfS )a  Gradients for the SparseReorder op.

  Args:
    op: the SparseReorder op
    unused_output_indices_grad: the incoming gradients of the output indices
    output_values_grad: the incoming gradients of the output values

  Returns:
    Gradient for each of the 3 input tensors:
      (input_indices, input_values, input_shape)
    The gradients for input_indices and input_shape is None.
  r   é   N)Śinputsr   Śshaper   Śranger   ŚSparseTensorr   Zsparse_reorderZinvert_permutationŚvaluesŚgather)
ŚopZunused_output_indices_gradZoutput_values_gradŚinput_indicesZinput_shapeZnum_entriesZentry_indicesZsp_unorderedZ
sp_orderedZinverted_permutation© r   śb/home/www/facesmatcher.com/pyenv/lib/python3.10/site-packages/tensorflow/python/ops/sparse_grad.pyŚ_SparseReorderGrad   s   


’
’’r   Z	SparseAddc                 G   st   |d }| j d }| j d }| jd }t ||||”\}}| | j d  ” ” | | j d  ” ” d|dd|ddfS )am  The backward operator for the SparseAdd op.

  The SparseAdd op calculates A + B, where A, B, and the sum are all represented
  as `SparseTensor` objects.  This op takes in the upstream gradient w.r.t.
  non-empty values of the sum, and outputs the gradients w.r.t. the non-empty
  values of A and B.

  Args:
    op: the SparseAdd op
    *grads: the incoming gradients, one element per output of `op`

  Returns:
    Gradient for each of the 6 input tensors of SparseAdd:
      (a_indices, a_values, a_shape, b_indices, b_values, b_shape, thresh)
    The gradients for the indices, shapes, and the threshold are None.
  é   r   é   é   N)r
   Śoutputsr   Zsparse_add_gradŚ	set_shapeŚ	get_shape)r   ŚgradsŚval_gradŚ	a_indicesZ	b_indicesZsum_indicesZ
a_val_gradZ
b_val_gradr   r   r   Ś_SparseAddGrad:   s   


’r   ZSparseTensorDenseAddc                 C   s   | j d }d t ||”d |fS )Nr   )r
   r   Ś	gather_nd)r   Śout_gradŚ
sp_indicesr   r   r   Ś_SparseTensorDenseAddGrad\   s   
r"   ZSparseReduceSumc                 C   s\   | j d }| j d }t || j d ”}t ||”}|t |tj” }dt ||| ”ddfS )z:Similar to gradient for the Sum Op (i.e. tf.reduce_sum()).r   r	   r   N)	r
   r   Zreduced_shaper   ZreshapeŚcastr   Śint64r   )r   r    r!   Zsp_shapeZoutput_shape_kept_dimsZout_grad_reshapedŚscaler   r   r   Ś_SparseReduceSumGradc   s   

’’r&   ZSparseSlicec                 G   sX   |d }| j d }| j d }| jd }t ||||”}| | j d  ” ” d|dddfS )a  The backward operator for the SparseSlice op.

  This op takes in the upstream gradient w.r.t. non-empty values of
  the sliced `SparseTensor`, and outputs the gradients w.r.t.
  the non-empty values of input `SparseTensor`.

  Args:
    op: the SparseSlice op
    *grads: the incoming gradients, one element per output of `op`

  Returns:
    Gradient for each of the 5 input tensors of SparseSlice:
      (indices, values, shape, start, size)
    The gradients for the indices, shape, start and the size are None.
  r   r   r   N)r
   r   r   Zsparse_slice_gradr   r   )r   r   Zbackprop_val_gradr   Zinput_startZoutput_indicesr   r   r   r   Ś_SparseSliceGradp   s   


’r'   ZSparseTensorDenseMatMulc                 C   s  | j dd \}}}| j d }|  d”}|  d”}|jj}|jj}	||	kr0td| d|	 dtj||||| d}
|rDtj|
d	d
}
|dddf }|dddf }t 	||s[|n|”}t 	|sd|nt 
|”|sl|n|”}|s|stjt |d”t |d”d	d}n=|r|stjt |d”t |d”d	d}n(|s¬|r¬t t |d”t |d””}n|rĮ|rĮtjt |d”t |d”d	d	d}dtj|ddgdd|
fS )a  Gradients for the dense tensor in the SparseTensorDenseMatMul op.

  Args:
    op: the SparseTensorDenseMatMul op
    grad: the incoming gradient

  Returns:
    Gradient for each of the 4 input tensors:
      (sparse_indices, sparse_values, sparse_shape, dense_tensor)
    The gradients for indices and shape are None.

  Raises:
    TypeError: When the two operands don't have the same type.
  Nr   Ś	adjoint_aŚ	adjoint_bzDSparseTensorDenseMatMul op received operands with different types: `z` and `z`.)r(   T)Ś	conjugater   r   éž’’’)r)   é’’’’)r(   r)   )Zaxis)r
   Zget_attrZdtypeZ
base_dtypeŚ	TypeErrorr   Zsparse_tensor_dense_mat_mulr   Zmatrix_transposer   Z	transposer   ŚmatmulŚexpand_dimsZsqueeze)r   Śgradr   Za_valuesZa_shapeŚbZadj_aZadj_bŚa_typeŚb_typeZb_gradŚrowsŚcolsZparts_aZparts_bZa_values_gradr   r   r   Ś_SparseTensorDenseMatMulGrad   sb   


’’’’’

ż

ż’

ür6   ZSparseDenseCwiseAddc                 C   ó   t d)Nz4Gradient for SparseDenseCwiseAdd is not implemented.©ŚNotImplementedError©Z	unused_opZunused_gradr   r   r   Ś_SparseDenseCwiseAddGradē   ó   ’r;   c                 C   s  | j d }| j d }| j d }t t |”tj”}t t |”t |” d”}t 	t 
|tjj”|gd”}|| }	||	 }
t |
t 	dg|gd”ddg”}
t ||
”}|ra|| }|| j d  }n|| }|| j d  t |”  }t t |”t |
||””}d|d|fS )z4Common code for SparseDenseCwise{Mul,Div} gradients.r   r	   r   r,   r   N)r
   r   r#   r   r   r   r$   r/   ŚsizeŚconcatZonesr   Śslicer   Zsquarer   Z
sparse_addŚ
zeros_liker   r   )r   r0   Zis_mulZ	x_indicesZx_shapeŚyZy_shapeZnum_added_dimsZaugmented_y_shapeZscalingZscaled_indicesZ
dense_valsZdxZdy_valZdyr   r   r   Ś_SparseDenseCwiseMulOrDivGradķ   s6   


’’žžrB   ZSparseDenseCwiseMulc                 C   ó   t | |dS )z"Gradients for SparseDenseCwiseMul.T©rB   ©r   r0   r   r   r   Ś_SparseDenseCwiseMulGrad  ó   rF   ZSparseDenseCwiseDivc                 C   rC   )z"Gradients for SparseDenseCwiseDiv.FrD   rE   r   r   r   Ś_SparseDenseCwiseDivGrad  rG   rH   ZSparseSoftmaxc                 C   s   | j d | j d }}| jd }t |||”}t |||”}t ||j|j |”}tj|dgdd }t ||”}	|	j|j }
d|
dgS )a³  Gradients for SparseSoftmax.

  The calculation is the same as SoftmaxGrad:

    grad_x = grad_softmax * softmax - sum(grad_softmax * softmax) * softmax

  where we now only operate on the non-zero values present in the SparseTensors.

  Args:
    op: the SparseSoftmax op.
    grad: the upstream gradient w.r.t. the non-zero SparseSoftmax output values.

  Returns:
    Gradients w.r.t. the input (sp_indices, sp_values, sp_shape).
  r   r	   r,   T)ZkeepdimsN)r
   r   r   r   r   r   Zsparse_reduce_sumZsparse_dense_cwise_add)r   r0   Śindicesr   Zout_valsZ	sp_outputZsp_gradZ
sp_productZsum_reducedZsp_sumZgrad_xr   r   r   Ś_SparseSoftmaxGrad  s   

ž
rJ   ZSparseSparseMaximumc                 C   r7   )Nz4Gradient for SparseSparseMaximum is not implemented.r8   r:   r   r   r   Ś_SparseSparseMaximumGrad=  r<   rK   ZSparseSparseMinimumc                 C   r7   )Nz4Gradient for SparseSparseMinimum is not implemented.r8   r:   r   r   r   Ś_SparseSparseMinimumGradC  r<   rL   ZSparseFillEmptyRowsc                 C   s(   | j d }tj||d\}}d|d|gS )z"Gradients for SparseFillEmptyRows.r   )Śreverse_index_mapZgrad_valuesN)r   r   Zsparse_fill_empty_rows_grad)r   Zunused_grad_output_indicesZoutput_grad_valuesZunused_grad_empty_row_indicatorZunused_grad_reverse_index_maprM   Zd_valuesZd_default_valuer   r   r   Ś_SparseFillEmptyRowsGradI  s
   

’rN   ZSparseToDensec                 C   sF   | j \}}}}t ||”}t |”t |” }t |”t |”||gS )N)r
   r   r   r   Z
reduce_sumr@   )r   r0   Zsparse_indicesZoutput_shapeŚ_Zsparse_values_gradZdefault_value_gradr   r   r   Ś_SparseToDenseGradW  s   ’žrP   N)Ś__doc__Ztensorflow.python.frameworkr   r   r   Ztensorflow.python.opsr   r   r   r   ZNotDifferentiableZRegisterGradientr   r   r"   r&   r'   r6   r;   rB   rF   rH   rJ   rK   rL   rN   rP   r   r   r   r   Ś<module>   sN   



!



Y
"


!


