
    AVhG5                        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j                  d	        ej                  d
        ej                  d      dej                  fd       Z ej                  d      dej                  fd       Z ej                  d      dej                  fd       Z ej                  d      dej                  fd       Z ej                  d      dej                  fd       Z ej                  d      dej                  fd       Z ej                  d      d        Zdej                  fdZ ej                  d      dej                  fd       Z ej                  d      dej                  fd       Z ej                  d      dej                  fd        Z ej                  d!      d"ej                  fd#       Z ej                  d$      d"ej                  fd%       Z ej                  d&      dej                  fd'       Z ej                  d(      dej                  fd)       Zy*)+z1Gradients for operators defined in sparse_ops.py.    )dtypes)ops)sparse_tensor)	array_ops)gen_sparse_ops)math_ops)
sparse_opsSparseAddGradSparseConcatSparseReorderopc                 `   | j                   d   }| j                   d   }t        j                  |      d   }t        j                  |      }t        j                  |||      }t        j                  |      }t        j                  |j                        }	dt        j                  ||	      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	   sparse_reorderinvert_permutationvaluesgather)
r   unused_output_indices_gradoutput_values_gradinput_indicesinput_shapenum_entriesentry_indicessp_unordered
sp_orderedinverted_permutations
             Q/home/dcms/DCMS/lib/python3.12/site-packages/tensorflow/python/ops/sparse_grad.py_SparseReorderGradr"      s      ))A,-		!+.q1+..--++M=,79,((6*"55j6G6GH
	  !3!578<
> >    	SparseAddc                 ^   |d   }| j                   d   }| j                   d   }| j                  d   }t        j                  ||||      \  }}|j	                  | j                   d   j                                |j	                  | j                   d   j                                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   sparse_add_grad	set_shape	get_shape)r   gradsval_grad	a_indices	b_indicessum_indices
a_val_grad
b_val_grads           r!   _SparseAddGradr4   <   s    $ 1X(iil)iil)

1+
 *99	9k3*jryy|--/0ryy|--/0

D$
D$	??r#   SparseTensorDenseAddc                 T    | j                   d   }d t        j                  ||      d |fS )Nr   )r   r   	gather_nd)r   out_grad
sp_indicess      r!   _SparseTensorDenseAddGradr:   ^   s+    yy|*
	##Hj94	JJr#   SparseReduceSumc                 8   | j                   d   }| j                   d   }t        j                  || j                   d         }t        j                  ||      }|t        j
                  |t        j                        z  }dt        j                  |||z        ddfS )z:Similar to gradient for the Sum Op (i.e. tf.reduce_sum()).r   r   r'   N)	r   r   reduced_shaper   reshapecastr   int64r7   )r   r8   r9   sp_shapeoutput_shape_kept_dimsout_grad_reshapedscales          r!   _SparseReduceSumGradrE   e   s     yy|*YYq\(#11(BIIaLI''2HI
hmm$:FLLI
I%
	##$5$.%$79:>
F Fr#   SparseSlicec                     |d   }| j                   d   }| j                   d   }| j                  d   }t        j                  ||||      }|j	                  | j                   d   j                                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   sparse_slice_gradr+   r,   )r   r-   backprop_val_gradr   input_startoutput_indicesr.   s          r!   _SparseSliceGradrL   r   s    " Ah))A,-		!+::a=.--.?.9>K(
RYYq\++-.
$d	++r#   SparseTensorDenseMatMulc                    | j                   dd \  }}}| j                   d   }| j                  d      }| j                  d      }|j                  j                  }|j                  j                  }	||	k7  rt	        d| d|	 d      t        j                  |||||       }
|rt        j                  |
d	
      }
|dddf   }|dddf   }t        j                  ||s|n|      }t        j                  |s|nt        j                  |      |s|n|      }|sC|sAt        j                  t        j                  |d      t        j                  |d      d	      }n|rC|sAt        j                  t        j                  |d      t        j                  |d      d	      }n|sA|r?t        j                  t        j                  |d      t        j                  |d            }nE|rC|rAt        j                  t        j                  |d      t        j                  |d      d	d	      }dt        j                  ddg      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`.)rO   T)	conjugater   r&   )rP   )rO   rP   )axis)r   get_attrdtype
base_dtype	TypeErrorr   sparse_tensor_dense_mat_mulr   matrix_transposer   	transposer   matmulexpand_dimssqueeze)r   gradr/   a_valuesa_shapebadj_aadj_ba_typeb_typeb_gradrowscolsparts_aparts_ba_values_grads                   r!   _SparseTensorDenseMatMulGradrm      s      "$2A)Xwiil!
++k
"%
++k
"%>>$$&77&v
876("	&' '
 557DI?&
''$?F, 
1a4$	1a4$Tu4$?'a)--a0e$O' 
uOOgr*gr*M UOOgr*gr*M U OOgr*I,A,A'2,NPM OOgr*gr*	M 	!!-r2h?v	NNr#   SparseDenseCwiseAddc                     t        d      )Nz4Gradient for SparseDenseCwiseAdd is not implemented.NotImplementedError	unused_opunused_grads     r!   _SparseDenseCwiseAddGradru      s    <	> >r#   c                    | j                   d   }| j                   d   }| j                   d   }t        j                  t        j                  |      t
        j                        }t        j                  t        j                  |      t        j                  |      z
  d      }t        j                  t        j                  |t        j
                  j                        |gd      }||z  }	||	z  }
t        j                  |
t        j                  dg|gd      ddg      }
t        j                  ||
      }|r||z  }|| j                   d   z  }n.||z  }|| j                   d    t        j                  |      z  z  }t        j                   t        j"                  |      t%        j&                  |
||            }d|d|fS )z4Common code for SparseDenseCwise{Mul,Div} gradients.r   r   r'   rS   r&   N)r   r   r?   r   r   r   r@   r]   sizeconcatonesr   slicer7   squarer	   
sparse_add
zeros_liker   r   )r   r_   is_mul	x_indicesx_shapeyy_shapenum_added_dimsaugmented_y_shapescalingscaled_indices
dense_valsdxdy_valdys                  r!   _SparseDenseCwiseMulOrDivGradr      s   iil)IIaL'iil!MM)//!,fll;'((nnW	w 77<.&&~~ncjj&6&67A1F ((''.??>#,#3#3aS.4I1#M$&8-. ""1n5*	
	BBIIaL F	
	Bbiil]X__Z%@@AF1  AC"
 D"	r#   SparseDenseCwiseMulc                     t        | |d      S )z"Gradients for SparseDenseCwiseMul.Tr   r   r_   s     r!   _SparseDenseCwiseMulGradr     s     
'r4	66r#   SparseDenseCwiseDivc                     t        | |d      S )z"Gradients for SparseDenseCwiseDiv.Fr   r   s     r!   _SparseDenseCwiseDivGradr     s     
'r4	77r#   SparseSoftmaxc                    | j                   d   | j                   d   }}| j                  d   }t        j                  |||      }t        j                  |||      }t        j                  ||j                  |j                  z  |      }t        j                  |dgd       }t        j                  ||      }	|	j                  |j                  z  }
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   rS   T)keepdimsN)r   r)   r   r   r   r	   sparse_reduce_sumsparse_dense_cwise_add)r   r_   indicesr   out_vals	sp_outputsp_grad
sp_productsum_reducedsp_sumgrad_xs              r!   _SparseSoftmaxGradr     s    " 99Q<15'ZZ]((((EB)&&we<'))'*3*:*:W^^*K*/1*
 --j2$NN+,,WkB&==9+++&
	r#   SparseSparseMaximumrs   c                     t        d      )Nz4Gradient for SparseSparseMaximum is not implemented.rp   rr   s     r!   _SparseSparseMaximumGradr   ?      <	 r#   SparseSparseMinimumc                     t        d      )Nz4Gradient for SparseSparseMinimum is not implemented.rp   rr   s     r!   _SparseSparseMinimumGradr   F  r   r#   SparseFillEmptyRowsc                 `    | j                   d   }t        j                  ||      \  }}d|d|gS )z"Gradients for SparseFillEmptyRows.r'   )reverse_index_mapgrad_valuesN)r)   r   sparse_fill_empty_rows_grad)r   unused_grad_output_indicesoutput_grad_valuesunused_grad_empty_row_indicatorunused_grad_reverse_index_mapr   d_valuesd_default_values           r!   _SparseFillEmptyRowsGradr   M  s>     jjm,HH)7I(O
 $	00r#   SparseToDensec                     | j                   \  }}}}t        j                  ||      }t        j                  |      t        j                  |      z
  }t        j
                  |      t        j
                  |      ||gS )N)r   r   r7   r   
reduce_sumr}   )r   r_   sparse_indicesoutput_shape_sparse_values_graddefault_value_grads          r!   _SparseToDenseGradr   `  s{    ')yy$.,1 **4@**4083F3F4  >*<(*<>P
 r#   N)__doc__tensorflow.python.frameworkr   r   r   tensorflow.python.opsr   r   r   r	   NotDifferentiableRegisterGradient	Operationr"   r4   r:   rE   rL   rm   ru   r   r   r   r   r   r   r   r    r#   r!   <module>r      s   8 . + 5 + 0 * ,   o &   n % o&>> '>: k"@s}} @ #@B ,-K#-- K .K '(	FS]] 	F )	F m$, , %,8 /0VOS]] VO 1VOr +,> ->
cmm D +,7 7 -7
 +,8 8 -8
 o&3==  'B +,  - +,  - +,11 -1$ o&	3== 	 '	r#   