
    AVh=                        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dlmZ d Zd Zd Zd Zd Z	 	 	 ddZ	 	 	 	 ddZ edg       ej8                  dd      	 	 	 	 dd              Zd Z edg       ej8                  dd      	 	 	 	 dd              Zy) zGradient checker for any ops, graphs.

The gradient checker verifies numerically that an op/graph properly
computes the gradients
    N)constant_op)dtypes)indexed_slices)ops)tensor)	array_ops)	gradients)math_ops)
tf_logging)deprecation)numpy_compat)	tf_exportc                 F    t        | t              r| S d}| D ]  }||z  }	 |S )N   )
isinstanceint)tyxs      V/home/dcms/DCMS/lib/python3.12/site-packages/tensorflow/python/ops/gradient_checker.py_productr   %   s3    3H	A 1faH    c                 V    | s|S i }|j                  |        |j                  |       |S )N)update)extra_feed_dict	new_feedsrs      r   _extra_feedsr   /   s-    	!((?((9	
(r   c                    | j                   j                  rt        |      dz   }|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                   j                  j                        }t        j                         }t        |
      D ]  }d||<   t        |t        j                        rt|j!                  |j"                  |j$                  gt'        || |||i            \  }}t)        ||      D ]*  \  }}||	z  }||	z   }||||fxx   |j*                  z  cc<   , n~t        |t,        j.                        sJ dt1        |      z          |j!                  |t'        || |||i            }|j                         j                  |j                         |dd|f<   d||<    |
s|j!                  |t'        || |||i            }|j2                  |j2                  k7  r%t5        d	|j2                  d
|j2                        t	        j6                  |      rt5        d      t9        j:                  dd|       |S )a1  Computes the theoretical Jacobian for dy/dx.

  Computes the theoretical Jacobian using the ops generated by
  compute_gradient().

  Args:
    x: the tensor "x".
    x_shape: the dimensions of x as a tuple or an array of ints.
    x_data: a numpy parray as the input data for x
    dy: the tensor "dy".
    dy_shape: the dimensions of dy as a tuple or an array of ints.
    dx: Tensor or IndexedSlices representing dx
    extra_feed_dict: dict that allows fixing specified tensor values
      during the jacobian calculation.

  Returns:
    A 2-d numpy array representing the Jacobian for dy/dx. It has "x_size" rows
    and "dy_size" columns where "x_size" is the number of elements in x and
    "dy_size" is the number of elements in dy.

  Raises:
    ValueError: If `dy` is empty but the gradient is nonzero.
  )   r    r   Ndtype	feed_dictzdx = r   z)Empty gradient has wrong shape: expected z, got z#Empty tensor with nonzero gradientszTheoretical Jacobian =
%s)r"   
is_complextupler   npzeros
real_dtypeas_numpy_dtyperavelviewr   get_default_sessionranger   r   IndexedSlicesrunindicesvaluesr   zipflatr   Tensorstrshape
ValueErroranyloggingvlog)r   x_shapex_datadydy_shapedxr   	dy_factorx_size
x_val_sizedy_sizejacobiandy_datady_data_flatsesscolbackprop_indicesbackprop_valuesivr_beginr_endbackprops                          r   _compute_theoretical_jacobianrQ   8   s   4 WWGnt#G88&&aA) G&$*X*' XXvw'GG..==?( HHXRXX%<%<='%%bhh&9&9&H&HI,		 	 	"$7^ cL"n223*.((::ryy
! 1fb'2JK +3 +M' &8 /$!Qj.*$#$.$/
 FMM*=Gc"g,==*
_q&"g6NO  Qh!)..x~~>hq#vL& 
xx
l?QG4LM  OH~~%hnn6 7 7	vvh<==	,,q.9	/r   c                 z   | j                   t        j                  k(  r$t        j                  | t        j
                        } |j                   t        j                  k(  r$t        j                  |t        j
                        }|j                   t        j                  j                  k(  r|j                  t        j
                        }t        |      | j                   j                  rdndz  }t        |      |j                   j                  rdndz  }| j                   j                  j                  }	|j                   j                  j                  }
t        j                  || j                   j                        }t        j                  d|z  |
      d   }t        j                  ||f|	      }t        |      D ]  }|j!                         }|j!                         }|j#                         j%                  |	      |xx   |z  cc<   |j'                  t)        || |i            }|j#                         j%                  |	      |xx   |z  cc<   |j'                  t)        || |i            }||z
  |z  }|j#                         j%                  |
      ||ddf<    t+        j,                  dd|       |S )a  Computes the numeric Jacobian for dy/dx.

  Computes the numeric Jacobian by slightly perturbing the inputs and
  measuring the differences on the output.

  Args:
    x: the tensor "x".
    x_shape: the dimensions of x as a tuple or an array of ints.
    x_data: a numpy array as the input data for x
    y: the tensor "y".
    y_shape: the dimensions of y as a tuple or an array of ints.
    delta: the amount of perturbation we give to the input
    extra_feed_dict: dict that allows fixing specified tensor values
      during the jacobian calculation.

  Returns:
    A 2-d numpy array representing the Jacobian for dy/dx. It has "x_size" rows
    and "y_size" columns where "x_size" is the number of elements in x and
    "y_size" is the number of elements in y.
  r    r   r!    r#   NzNumeric Jacobian =
%s)r"   r   bfloat16r
   castfloat32r*   astyper'   r   r%   r)   r   
np_asarrayr(   r.   copyr+   r,   evalr   r:   r;   )r   r<   r=   r   y_shapedeltar   rB   y_sizex_dtypey_dtypescalerE   rowx_posx_negy_posy_negdiffs                      r   _compute_numeric_jacobianrg      s   2 WWa(AWWa(A\\V__333]]2::&F GQWW%7%7Q?&GQWW%7%7Q?&GG--'GG--' ""61G1GH&

!
!!e)7
;B
?%XXvv&g6( 6] 2cKKMEKKME	KKMw$-$FF\/Au:FFGE	KKMw$-$FF\/Au:FFGEEMU"Dzz|((1HS!V2 
,,q*H5	/r   c                 *   | j                   j                         5  t        j                  d||j                        }t        j                  |      }ddd       t        j                  ||       }t        |      dk(  sJ |d   fS # 1 sw Y   7xY w)z.Returns a node to compute gradient of y wrt x.g      ?)r7   r"   Nr   r   )	graph
as_defaultr   constantr"   r   identityr	   len)r   r   r[   dy_origr>   gradss         r   _compute_dx_and_dyrp      s     	ww %""3gQWWEG			G	$B% 

aB
'%	Uq	q7	% %s   8B		Bc	           	      H   t        j                  | j                        }	t         j                  t         j                  t         j
                  t         j                  t         j                  t         j                  g}
|	j                  |
v sJ d|	j                  z         t        j                  |j                        }|j                  |
v sJ d|j                  z         |3t        |j                        }t        |      |k(  sJ d|d|       |}nht        j                  j                  |      j!                  |	j"                        }|	j$                  r$t        j                  j                  |      |_        t)        | ||||||      }t+        | ||||||      }||fS )z0Computes the theoretical and numerical jacobian.zDon't support type %s for xzDon't support type %s for yz
x_shape = z, init_data shape = r   )r   as_dtyper"   float16rT   rV   float64	complex64
complex128
base_dtypenamelistr7   r'   randomrandom_samplerW   r*   r%   imagrQ   rg   )r   r<   r@   r   r[   r>   x_init_valuer\   r   r   allowed_typest2i_shaper=   jacob_tjacob_ns                   r   _compute_gradientr      s[    ooagg!>>6??FNN>>6#3#3V5F5FH-	
	&N(E(NN	&qww"	-	'P)F)PP	'<%%&G=G# ' #FYY$$W-44Q5E5EFF||II++G4fk)&"gr?L'%&!We_N'	'	r   c                    t        | t              sJ t        | D cg c]  }t        |||       c} \  }	}
|/t        |t        t        f      sJ |D ]  }|j                           |dgt        |       z  }t        | ||	|
|      D cg c]  \  }}}}}t        |||||||||	       }}}}}}|S c c}w c c}}}}}w )z)Compute gradients for a list of x values.Nrr   )r   rz   r3   rp   r&   r0   rm   r   )r   r<   r   r[   r~   r\   init_targetsr   xir@   r>   initx_shapeidxidyix_init_valueirets                    r   _compute_gradient_listr      s     
At		a@#B73@A&"blT5M222 
hhj6CF?L 7:!Wb":F7H	I 	I2R3] 
2xa#} /
C 	I# 	I 
* A	Is   B7!B<ztest.compute_gradient)v1zUse tf.test.compute_gradient in 2.0, which has better support for functions. Note that the two versions have different usage, so code change is needed.)dateinstructionsc                     |i }t        | t              rt        | |||||||      S |/t        |t        t        f      sJ |D ]  }|j	                           t        | ||      \  }	}
t        | ||	|||
|||	      }|S )a  Computes and returns the theoretical and numerical Jacobian.

  If `x` or `y` is complex, the Jacobian will still be real but the
  corresponding Jacobian dimension(s) will be twice as large.  This is required
  even if both input and output is complex since TensorFlow graphs are not
  necessarily holomorphic, and may have gradients not expressible as complex
  numbers.  For example, if `x` is complex with shape `[m]` and `y` is complex
  with shape `[n]`, each Jacobian `J` will have shape `[m * 2, n * 2]` with

      J[:m, :n] = d(Re y)/d(Re x)
      J[:m, n:] = d(Im y)/d(Re x)
      J[m:, :n] = d(Re y)/d(Im x)
      J[m:, n:] = d(Im y)/d(Im x)

  Args:
    x: a tensor or list of tensors
    x_shape: the dimensions of x as a tuple or an array of ints. If x is a list,
    then this is the list of shapes.
    y: a tensor
    y_shape: the dimensions of y as a tuple or an array of ints.
    x_init_value: (optional) a numpy array of the same shape as "x"
      representing the initial value of x. If x is a list, this should be a list
      of numpy arrays.  If this is none, the function will pick a random tensor
      as the initial value.
    delta: (optional) the amount of perturbation.
    init_targets: list of targets to run to initialize model params.
    extra_feed_dict: dict that allows fixing specified tensor values
      during the Jacobian calculation.

  Returns:
    Two 2-d numpy arrays representing the theoretical and numerical
    Jacobian for dy/dx. Each has "x_size" rows and "y_size" columns
    where "x_size" is the number of elements in x and "y_size" is the
    number of elements in y. If x is a list, returns a list of two numpy arrays.
  rr   )r   rz   r   r&   r0   rp   r   )r   r<   r   r[   r~   r\   r   r   r   r@   r>   r   s               r   compute_gradientr     s    d O4!!Wa,".Q Q tUm444 $
1g.FB
AwAwL%,;=CJr   c                     t        | t              r| g} d}| D ]X  \  }}|j                  s|j                  st        j                  |t        j
                  ||z
        j                               }Z |S )Nr   )r   r&   sizer'   maximumfabsmax)graderrorj_tj_ns       r   _compute_errorr   Q  se    e6D
% :hc3
xx388jjc	 2 6 6 89e: 
,r   ztest.compute_gradient_errorc           
      >    t        | |||||||      }t        |      S )aJ  Computes the gradient error.

  Computes the maximum error for dy/dx between the computed Jacobian and the
  numerically estimated Jacobian.

  This function will modify the tensors passed in as it adds more operations
  and hence changing the consumers of the operations of the input tensors.

  This function adds operations to the current session. To compute the error
  using a particular device, such as a GPU, use the standard methods for
  setting a device (e.g. using with sess.graph.device() or setting a device
  function in the session constructor).

  Args:
    x: a tensor or list of tensors
    x_shape: the dimensions of x as a tuple or an array of ints. If x is a list,
    then this is the list of shapes.
    y: a tensor
    y_shape: the dimensions of y as a tuple or an array of ints.
    x_init_value: (optional) a numpy array of the same shape as "x"
      representing the initial value of x. If x is a list, this should be a list
      of numpy arrays.  If this is none, the function will pick a random tensor
      as the initial value.
    delta: (optional) the amount of perturbation.
    init_targets: list of targets to run to initialize model params.
    extra_feed_dict: dict that allows fixing specified tensor values
      during the Jacobian calculation.

  Returns:
    The maximum error in between the two Jacobians.
  rr   )r   r   )	r   r<   r   r[   r~   r\   r   r   r   s	            r   compute_gradient_errorr   [  s,    Z 
!Wa,&
I$		r   )NMbP?N)Nr   NN) __doc__numpyr'   tensorflow.python.frameworkr   r   r   r   r   tensorflow.python.opsr   r	   r
   tensorflow.python.platformr   r:   tensorflow.python.utilr   r    tensorflow.python.util.tf_exportr   r   r   rQ   rg   rp   r   r   
deprecatedr   r   r   rS   r   r   <module>r      s	   
  3 . 6 + . + + * < . / 6K\:z* $( &*L )-!%(,+/4 &'(	 ! #'"&%):! ):z ,-.	 ! )-!%(,+/)! /)r   