
    AVht2                         d Z ddl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 Zd Zd Zd Zd Zd Zd Zd Z edg       dd       Zd Zy)z|Gradient checker for functions.

The gradient checker verifies numerically that an function properly
computes the gradients
    N)backprop)context)dtypes)indexed_slices)ops)tensor)	array_ops)gradients_impl)
tf_logging)numpy_compat)	tf_exportc                 F    t        | t              r| S d}| D ]  }||z  }	 |S )N   )
isinstanceint)tyxs      Y/home/dcms/DCMS/lib/python3.12/site-packages/tensorflow/python/ops/gradient_checker_v2.py_productr   #   s3    3H	A 1faH    c                 R   t        | t        j                        rt        j                         rnt        j
                  | j                  D cg c]  }|j                          c}| j                  D cg c]  }|j                          c}| j                        S | S c c}w c c}w )aY  Converts IndexedSlices to IndexedSlicesValue with numpy indices/values.

  When eager execution is enabled, converts IndexedSlices
  to IndexedSlicesValue with numpy indices/values.

  Args:
    a: any value.

  Returns:
    If a is IndexedSlices and eager execution is enabled, calls numpy() on a's
    fields. Otherwise returns a unchanged.
  )indicesvaluesdense_shape)
r   r   IndexedSlicesr   executing_eagerlyIndexedSlicesValuer   numpyr   r   )ar   s     r   _eval_indexed_slicesr!   -   sy     N001!,,$%II.q.#$88,a	,MM# # 
( /,s   B3B$
c                    t        | t        j                        r| j                         S t        | t        j
                        r%t        j                         }|j                  |       S t        | t        j                        rt        j                  | j                        }t        | j                        t        | j                        k(  s$J d| j                  d| j                  d|        t!        | j                  | j                        D ]5  \  }}d|cxk  rt        |      k  sn J d|d|        ||xx   |z  cc<   7 |S | S )a@  Converts Tensors, EagerTensors, and IndexedSlicesValue to numpy arrays.

  Args:
    a: any value.

  Returns:
    If a is EagerTensor or Tensor, returns the evaluation of a by calling
    numpy() or run(). If a is IndexedSlicesValue, constructs the corresponding
    dense numpy array. Otherwise returns a unchanged.
  zIndexedSlicesValue has z value slices but z	 indices
r   z%IndexedSlicesValue has invalid index 
)r   r   EagerTensorr   r   Tensorget_default_sessionrunr   r   npzerosr   lenr   r   zip)r    sessarrvalues_sliceindexs        r   	_to_numpyr0   C   s
    3??#7796==!""$D88A;>445
((1==
!Cqxx=C		N* "	
199a	!"*  #188QYY7 !e%"#c(" F;@!
DF"	%jL j! J	
(r   c                     	 t        j                         r fd}|S t        ||      D cg c]  \  }}t        j                  ||       c}}   	t        j                         	fd}|S c c}}w )a,  Return a function that executes 'f'.

    In TF 2.x, this is the same as `f`.
    In TF 1.x, returns a Python function that executes the graph defined by `f`
    in a Session.

  Args:
    f: the function.
    xs_dtypes: dtypes of f's arguments.
    xs_shapes: shapes of f's arguments.

  Returns:
  c                  >     t        t        j                  |        S N)mapr   convert_to_tensor)xs_datafs    r   decorated_eagerz!_prepare.<locals>.decorated_eagerp   s    C))7344r   )shapec            	          | D cg c]  }t        |       } }j                  t        t        |                   S c c}w )N)	feed_dict)r0   r'   dictr+   )r6   r    r,   xsr   s     r   decorated_graphz!_prepare.<locals>.decorated_graph{   s>    %,-y|-G-88Ac"g&6!7888 .s   A )r   r   r+   r	   placeholderr   r&   )
r7   	xs_dtypes	xs_shapesr8   x_dtypex_shaper>   r,   r=   r   s
   `      @@@r   _preparerD   `   s{      5  ")Y7
'7 G73" f!		 	 	"$9 
s   !A6c           	         ||   }|j                   j                  rt        |j                        dz   n|j                  }|j                  rdnd}t	        |      }t	        |dd       }	t	        |      |z  }
t        j                  |
|f|j                   j                  j                        }t        j                  ||j                        }|j                         j                  |j                  j                        }t        j                  | |g      t        fd|g|D cg c]  }|j                    c}z   dg|D cg c]  }|j                   c}z         }t        |
      D ]  }d||<   t         ||g| d         }t!        |      }t#        |t$        j&                        rNt)        |j*                  |j,                        D ]*  \  }}||	z  }||	z   }||||fxx   |j.                  z  cc<   , n2|0|j                         j                  |j                         ||ddf<   d||<    |
dk(  rst         ||g| d         }|j                  |j                  k7  r%t1        d|j                  d	|j                        t        j2                  |      rt1        d
      t5        j6                  dd|       |S c c}w c c}w )aY  Computes the theoretical Jacobian for f regarding xs[param].

  One can think of the relation among f, xs and y as y = f(xs).

  Args:
    f: the function.
    y_shape: the shape of the result.
    y_dtype: the dtype of the result.
    xs: a list of tensors.
    param: the index of the target parameter.

  Returns:
    A 2-d numpy array representing the Jacobian. It has "y_size" rows
    and "x_size" columns where "x_size" is the number of elements in xs[param]
    and "y_size" is the number of elements in the result.

  Raises:
    ValueError: If result is empty but the gradient is nonzero.
  )   rF   r   Ndtypec                      |d| iS )Ndy )rJ   r=   grad_fn_unpreps     r   <lambda>z/_compute_theoretical_jacobian.<locals>.<lambda>   s    ^R%?B%? r   r   z)Empty gradient has wrong shape: expected z, got z#Empty tensor with nonzero gradientszTheoretical Jacobian =
%s)rH   
is_complextupler9   r   r(   r)   
real_dtypeas_numpy_dtyperavelviewr   gradients_functionrD   ranger0   r!   r   r   r   r+   r   r   flat
ValueErroranyloggingvlog)r7   y_shapey_dtyper=   paramr   rC   y_factorx_size
x_val_sizey_sizejacobiandy_datady_data_flatzgrad_fnrowgradivc_beginc_endrL   s                         @r   _compute_theoretical_jacobianrm      s   ( 	i!%&WW%7%7E!''NT!QWW'$$Q!( G&$*Gx'& XXvv&agg.@.@.O.OP(
 HHWG$:$:;'%%g&8&8&G&GH,..q5':.?Y2!6a!''!66V31qww335' 6] cLWW*r*1-.D%D$99:dllDKK0 /$!Qj.*$gem#$.$/ 
	**8>>:hsAv L" q[WW*r*1-.DzzQWW- . .	vvd|<==	,,q.9	/9 "73s   )KKc                    ||   j                   }||   j                  }t        |      |j                  rdndz  }||j                  rdndz  }|j                  j
                  }|j                  j
                  }|D 	cg c]  }	|	j                   }
}	|D 	cg c]  }	|	j                    }}	|D 	cg c]   }	t        j                  t        |	            " }}	||   }	t        j                  d|z  |      d   }t        j                  ||f|      }t        | |
|      } t        |      D ]  }|	j                         j                  |      |   }|	j                         j                  |      |xx   |z  cc<   t         | |       }||	j                         j                  |      |<   |	j                         j                  |      |xx   |z  cc<   t         | |       }||	j                         j                  |      |<   ||z
  |z  }|j                         j                  |      |dd|f<   
 t        j                   dd|       |S c c}	w c c}	w c c}	w )aR  Computes the numeric Jacobian for f regarding xs[param].

  One can think of the relation among f, xs and y as y = f(xs).

  Args:
    f: the function.
    y_size: the number of elements of the result.
    y_dtype: the dtype of the result.
    xs: a list of tensors.
    param: the index of the target parameter.
    delta: the amount of perturbation we give to the input.

  Returns:
    A 2-d numpy array representing the Jacobian. It has "y_size" rows
    and "x_size" columns where "x_size" is the number of elements in xs[param]
    and "y_size" is the number of elements in the result.
  rF   r   rG   rK   NzNumeric Jacobian =
%s)r9   rH   r   rN   rP   rQ   r   
np_asarrayr0   r(   r)   rD   rU   rR   rS   rY   rZ   )r7   ra   r\   r=   r]   deltarC   rB   r_   r   r@   rA   scalerb   coloriginaly_posy_negdiffs                      r   _compute_numeric_jacobianrw      s   $ uIOO'uIOO' GW%7%7Q?&',,Q!4&--'--' "#1qww#)# "#1qww#)# 8::!	!-:":i! 
!
!!e)7
;B
?%XXvv&g6(
 q)Y'!6] 	2cwwy~~g&s+HGGINN7C E) afE#+AGGINN7C GGINN7C E) afE#+AGGINN7C EMU"Dzz|((1HQV	2 
,,q*H5	/9 $# ;s   >II0%Ic                    ||   }|j                   }t        j                  t        j                  t        j                  t        j
                  t        j                  t        j                  g}|j                  |v sJ d|j                  d|       |}	|	j                  |v sJ d|	j                  z         t        |      }
t        | ||||      }t        | |
||||      }||fS )z0Computes the theoretical and numerical jacobian.z-Cannot compute gradient for unsupported type z of argument z4Cannot compute gradient for unsupported type %s of y)rH   r   float16bfloat16float32float64	complex64
complex128
base_dtypenamer   rm   rw   )r7   r[   r\   r=   r]   rp   r   r   allowed_typest2ra   jacob_tjacob_ns                r   _compute_gradientr     s    i!gg!nnfoov~~v~~))- 
	& :*+&&%*9 :	& "	-	' P +EGIww+O P	'G&)!Wgr5I'%a"eUK'	'	r   c                    |D cg c]  }t        j                  |       }}|D cg c]  }|j                   }}|D cg c]  }|j                   }}t	        | ||      } || }t        t        t        t        |            D cg c]9  }t        | |j                  t        j                  |j                        |||      ; c}       S c c}w c c}w c c}w c c}w )z)Compute gradients for a list of x values.)r   r5   rH   r9   rD   rO   r+   rU   r*   r   r   as_dtype)	r7   r=   rp   r   r@   rA   f_tempr   ri   s	            r   _compute_gradient_listr     s     +--Qa -"- "#1qww#)# "#1qww#)#Ay),&bk!		R> Aqww(@"a
O 	

 
 .##s   CC C>Cztest.compute_gradient)v1c                 ~    t        |t        t        f      st        dt	        |      z        |d}t        | ||      S )a  Computes the theoretical and numeric Jacobian of `f`.

  With y = f(x), computes the theoretical and numeric Jacobian dy/dx.

  Args:
    f: the function.
    x: the arguments for the function as a list or tuple of values convertible
      to a Tensor.
    delta: (optional) perturbation used to compute numeric Jacobian.

  Returns:
    A pair of lists, where the first is a list of 2-d numpy arrays representing
    the theoretical Jacobians for each argument, and the second list is the
    numerical ones. Each 2-d array has "y_size" rows
    and "x_size" columns where "x_size" is the number of elements in the
    corresponding argument and "y_size" is the number of elements in f(x).

  Raises:
    ValueError: If result is empty but the gradient is nonzero.
    ValueError: If x is not list, but any other type.

  Example:

  >>> @tf.function
  ... def test_func(x):
  ...   return x*x
  ...
  >>>
  >>> class MyTest(tf.test.TestCase):
  ...
  ...   def test_gradient_of_test_func(self):
  ...     theoretical, numerical = tf.test.compute_gradient(test_func, [1.0])
  ...     # ((array([[2.]], dtype=float32),),
  ...     #  (array([[2.000004]], dtype=float32),))
  ...     self.assertAllClose(theoretical, numerical)

  zZ`x` must be a list or tuple of values convertible to a Tensor (arguments to `f`), not a %sg      P?)r   listrO   rW   typer   )r7   r   rp   s      r   compute_gradientr   (  sN    N 
Ae}	%
	')-a	12 2 ]
 E	1e	,,r   c                     d}t        | |      D ]X  \  }}|j                  s|j                  st        j                  |t        j                  ||z
        j                               }Z |S )a  Computes maximum elementwise gap.

  Computes the maximum elementwise gap between two lists of tensors of the same
  shape.

  Args:
    grad1: a lists of tensors.
    grad2: a lists of tensors with the same shape as grad1.

  Returns:
    The maximum elementwise gap between the two.
  r   )r+   sizer(   maximumfabsmax)grad1grad2errorj_tj_ns        r   	max_errorr   \  s]     %eU# :hc3
xx388jjc	 2 6 6 89e: 
,r   r3   )__doc__r   r(   tensorflow.python.eagerr   r   tensorflow.python.frameworkr   r   r   r   tensorflow.python.opsr	   r
   tensorflow.python.platformr   rY   tensorflow.python.utilr    tensorflow.python.util.tf_exportr   r   r!   r0   rD   rm   rw   r   r   r   r   rK   r   r   <module>r      s~   
  , + . 6 + . + 0 < / 6,:DEP7t(
  "r*0- +0-fr   