
    AVhy                     R   d Z ddl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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dl%m&Z& ddl'm(Z( d Z)de*ejV                     de*ejV                     fd Z,d! Z-	 dDd"Z.d#ejV                  fd$Z/de*ejV                     d%e*ejV                     fd&Z0ejb                  d#ejV                  fd'       Z2d#ejV                  fd(Z3d#ejV                  fd)Z4d#ejV                  fd*Z5d#ejV                  de*ejV                     fd+Z6d, Z7d- Z8d. Z9d#ejV                  fd/Z:d#ejV                  fd0Z;d1 Z<dd2d3d3ddejz                  dfd4Z>d#ejV                  fd5Z?d#ejV                  fd6Z@d7 ZAd8 ZBd9 ZCd#ejV                  fd:ZDd; ZEd#ejV                  fd<ZFd= ZG e(d>       G d? d>             ZH	 dEd@ZIdZJdAZKdBZLdC ZMy)Fz=Implements the graph generation for computation of gradients.    N)attr_value_pb2)
pywrap_tfe)backprop_util)context)composite_tensor)composite_tensor_gradient)dtypes)indexed_slices)ops)tensor)tensor_shape)	array_ops)control_flow_ops)control_flow_state)control_flow_util)default_gradient)gen_functional_ops)math_ops)resource_variable_ops)UnconnectedGradients)
tf_logging)compat)object_identity)variable_utils)collections_abc)	tf_exportc                 (   t        j                         }|j                  |        |rk|j                         }||vrS|j	                  |       |j
                  D ]3  }t        j                  |      s|j                  t        ||             5 |rjyy)a  Mark all ops reached from "from_ops".

  Args:
    from_ops: list of Operations.
    reached_ops: set of Operations.
    func_graphs: list of FuncGraphs. This method will traverse through
      these functions if they capture from_ops or any reachable ops.
  N)	collectionsdequeextendpopleftaddoutputsr   IsTrainable
_Consumers)from_opsreached_opsfunc_graphsqueueopoutputs         T/home/dcms/DCMS/lib/python3.12/site-packages/tensorflow/python/ops/gradients_util.py_MarkReachedOpsr-   0   sy     


%,,x	B	oobJJ 8&$$V,
,,z&+6
78	 	    to_opsr&   c                    t               t        ||       t        fd| D              }t               }g }t        j                         }|j	                  |        |rv|j                         }	|	v r_|j                  |	       |j                  |	       j                  |	       t        |	|      D ]  }
|j                  |
j                          |rvt        j                  |||      }t        j                  t              }|D ]9  }	t        |	|      D ](  }|j                  |v s||j                  xx   dz  cc<   * ; |||fS )a  Initialize the pending count for ops between two lists of Operations.

  'pending_count[op]' indicates the number of backprop inputs
  to this operation.

  Args:
    to_ops: list of Operations.
    from_ops: list of Operations.
    colocate_gradients_with_ops: Python bool.  See docstring of gradients().
    func_graphs: list of FuncGraphs. This method will traverse through
      these functions if they capture from_ops or any reachable ops. This is
      useful if to_ops occur in a function and from_ops are in an outer function
      or graph.
    xs_set: ObjectIdentitySet of Tensors.

  Returns:
    A tuple containing: (1) the subset of to_ops reachable from from_ops by a
    path of zero or more backpropagatable tensors, (2) a mapping from operation
    to the number of backprop inputs to that op, and (3) a ControlFlowState
    object which is not None if the ops between from_ops and to_ops contain
    control flow loops.
  c              3   ,   K   | ]  }|v s|  y wN ).0r*   r'   s     r,   	<genexpr>z _PendingCount.<locals>.<genexpr>g   s     Bk0ABs   	   )setr-   r   r   r    r!   r"   appendremove_NonEagerInputsr*   r   MaybeCreateControlFlowStatedefaultdictint)r/   r&   colocate_gradients_with_opsr(   xs_setreachable_to_opsbetween_opsbetween_op_listr)   r*   inp
loop_statepending_countxr'   s                 @r,   _PendingCountrG   D   s=   < +(K5 BfBB +/



%,,v	B	[oobR  V, #SVV 	 "=={$?A* ))#.- !bR( !	
	addq !!
 
=*	44r.   c                 8    t        | t        t        f      r| S | gS r2   )
isinstancelisttuplerF   s    r,   _AsListrM      s    T5M*33r.   c                 2
   t        |       t        |      k7  r$t        dt        |        dt        |       d      t        j                  | d      } g }t	        t        ||             D ]  \  }\  }}t        |j                  ||      5  ||j                  j                  r9t        d| dt        j                  |j                        j                   d	      |j                  t        j                   t        j"                  |      |j                  d
|z               	 ddd       |j                  j$                  s|j                  j&                  r|j                  j$                  s,|j                  j&                  st        dt        j                  |j                        j                   d| dt        j                  |j                        j                   d      |j                  j                  rz|j                  j                  st        dt        j                  |j                        j                   d| dt        j                  |j                        j                   d      |j                  t        j(                  k(  r|j                  t        j(                  k7  rt        dt        j                  |j                        j                   d| dt        j                  |j                        j                   d      |j                  t        j*                  k(  r/|j                  t        j*                  k(  rKt        d| d| d      t        d| dt        j                  |j                        j                   d      t-        |t        j.                        r|j                  t        j.                  t-        |j0                  t2        j4                        r$t        j6                  |j0                  d|z        n|j0                  t-        |j8                  t2        j4                        r$t        j6                  |j8                  d|z        n|j8                  t-        |j:                  t2        j4                        r$t        j6                  |j:                  d|z        n|j:                               n)|j                  t        j6                  |d
|z               ddd        |S # 1 sw Y   xY w)aG  Fill in default values for grad_ys.

  Args:
    grad_ys: List of gradients, can contain None.
    ys: List of tensors.
    colocate_gradients_with_ops: If True, try colocating gradients with
      the corresponding op.
    gradient_uid: A unique identifier within the graph indicating
      which invocation of gradients is being executed. Used to cluster
      ops for compilation.

  Returns:
    A list of gradients to use, without None.

  Raises:
    ValueError: If sizes of gradients and inputs don't match
    TypeError: If type of any gradient is not valid for its input.
  zLength mismatch. Passed z grad_ys for z ysgrad_ynameNzGradients of complex tensors (z) must set grad_ys (y.dtype = )z
grad_ys_%d)dtyperQ   zGradient type z- generated for real or integer-valued tensor z with type z must be real or integerz% generated for complex-valued tensor z must be realz generated for variant tensor z must be variantzInput gradient z for resource tensor z should not be a resourcezTensor z- must be numeric to obtain a default gradientzgrad_ys_%d_indiceszgrad_ys_%d_valueszgrad_ys_%d_shape)indicesvaluesdense_shape)len
ValueErrorr
   %convert_n_to_tensor_or_indexed_slices	enumeratezip_maybe_colocate_withr*   rS   
is_complex	TypeErrorr	   as_dtyperQ   r8   r   onesshapeis_floating
is_integervariantresourcerI   IndexedSlicesrT   
tensor_libTensoridentityrU   rV   )grad_ysysr>   gradient_uidnew_grad_ysiyrO   s           r,   _DefaultGradYsrp      sZ   , 	\SW
/G~]By% & &@@H'+!#b'"23 NNna!V	addL2M	N MN	77.qc1O)../q2  	NN"!''q8H	

 	MN MN 
		 2 2||''0G0Gvv||<AAB C334#[)..//GI 
 77||&&vv||<AAB C++,#[)../}> 
 77fnn$<<6>>)vv||<AAB C$$%3k)..//?A 
 77foo% <<6??*x'<QC @) ) 
 aSFOOAGG$<$A$A#B C3 3
 	
 
FN88	9((
 "&..*2C2CD &&-AA-E   "&--1B1BC &&,?!,C   "&"4"4j6G6GH &&**1Ca1G  ++)	
4 	9--f<!;KLM[MN MNNN` 
_MN MNs   BT.OTT	r*   c           
          |j                   dk(  s|j                   dk(  ryt        |       t        |j                        k7  r:t        dt        |        d|j                   dt        |j                               y)a.  Verify that gradients are valid in number and type.

  Args:
    grads: List of generated gradients.
    op: Operation for which the gradients where generated.

  Raises:
    ValueError: if sizes of gradients and inputs don't match.
    TypeError: if type of any gradient is not valid for its input.
  WhileStatelessWhileNzNum gradients z generated for op z do not match num inputs )typerW   inputsrX   node_def)gradsr*   s     r,   _VerifyGeneratedGradientsrx      sr     WW277&66
Z3ryy>!

U$6;;-0RYY0@	B  "r.   stop_gradient_opsc                     t               }| D ]?  }d}t        ||      D ]  }||j                     dkD  sd} n |s/|j                  |       A |j	                  d |D               |S )a  The set of ops that terminate the gradient computation.

  This computes the frontier of the forward graph *before* which backprop
  should stop. Operations in the returned set will not be differentiated.
  This set is defined as the subset of `from_ops` containing ops that have
  no predecessor in `from_ops`. `pending_count` is the result of
  `_PendingCount(xs, from_ops)`. An 'op' has predecessors in `from_ops`
  iff pending_count[op] > 0.

  In addition, none of `stop_gradient_ops` will be differentiated.

  Args:
    from_ops: list of Operations.
    stop_gradient_ops: list of Operations never to backprop through.
    pending_count: mapping from operation to number of backprop inputs.
    xs_set: ObjectIdentitySet of Tensors.

  Returns:
    The set of operations.
  Tr   Fc              3       K   | ]  }|  y wr2   r3   )r4   r*   s     r,   r5   z_StopOps.<locals>.<genexpr>6  s     1"1s   )r7   r:   r*   r"   update)r&   ry   rE   r?   stop_opsr*   
is_stop_oprC   s           r,   _StopOpsr     sy    4 U( bJr6* 	svv		"
 ll2 //1011	/r.   c              #   x   K   |r$t        j                  | |      5  d ddd       yd y# 1 sw Y   yxY ww)z?Context to colocate with `op` if `colocate_gradients_with_ops`.N)r   _colocate_with_for_gradient)r*   rl   r>   s      r,   r\   r\   :  s<      !		(	(\	:   
 s   :.:7:c                 B    | j                   dk(  xs | j                   dk(  S )NPartitionedCallStatefulPartitionedCall)rt   r*   s    r,   _IsPartitionedCallr   H  s!    	%	%	M4M)MMr.   c                    | j                   D cg c]  }| c}|z   }| j                   D cg c]  }t        j                  |       }}t        j                         }t        |       r!| j                  d      j                  |_        n| j                  |_        | j                  j                  D ]7  }|j                  |   j                  | j                  j                  |          9 t        j                  |||      }|S c c}w c c}w )zFBackprop through a function call node op given its outputs' gradients.f)inputToutr   )ru   r   get_zeros_dtyper   NameAttrListr   get_attrrQ   rt   rv   attrCopyFromr   symbolic_gradient)r*   	out_gradsrF   f_inf_typesr   kin_gradss           r,   _SymGradr   L  s    YY	!	)	+$:<))DQ--a0D'D!!#![[""AFWWAF;; ,aFF1Ir{{''*+,117aP(	/ 
 Ds
   	DD
c                    | j                  d      j                  dd      } |x|j                  j                  d   j                  }|j                  j                  d   j                  }|j                  j                  d   j
                  j                         }nB	 |j                  d      }|j                  d      }|j                  d      j                         }|s |       S rd| }n}t        j                  |	      t        j                  |j                         
      d}t        j                         j                  |      5   |       cddd       S # t        $ r d}Y w xY w# 1 sw Y   yxY w)z@Compile the calculation in grad_fn if op was marked as compiled./_N_XlaCompile_XlaSeparateCompiledGradients	_XlaScopeF_grad_)b)s)r   r   )rstripreplacecached_definitionr   r   r   decoder   rX   r   	AttrValueencoder   get_default_graph_attr_scope)	scoper*   funcgrad_fnxla_compilexla_separate_compiled_gradients	xla_scopexla_grad_scopeattrss	            r,   _MaybeCompiler   [  s^   
,,s

#
#C
-%	((--m<>>K&*&<&<&A&A''))* $&&++K8::AACIKK.k(*
))+%++k*113i 
9 %%.6NN $--<!++n.C.C.EF% **51 9 '  k& s   AE" E3"E0/E03E<c                 (   d}t        j                  | g      }t               }|rR|j                         }||v r|j	                  |       ||v r|}n%|j                  d t        ||      D               |rR|sJ t        d|j                   d      )z2Raises an error if we backprop through a loop var.Nc              3   4   K   | ]  }|j                     y wr2   r   )r4   ts     r,   r5   z5_RaiseNoGradWrtInitialLoopValError.<locals>.<genexpr>  s     @!@s   z>Cannot compute gradient inside while loop with respect to op 'z'. We do not support taking the gradient wrt or through the initial value of a loop variable. Gradients can be computed through loop invariants or wrt the input parameters to the loop body.)	r   r   r7   r!   r"   r    r:   rX   rQ   )r*   r&   r?   	target_opr)   visitedcurr_ops          r,   "_RaiseNoGradWrtInitialLoopValErrorr     s     )


RD
!%E'mmoG'8KK(i	LL@w?@@ 	 


..	 NN	O Or.   c                 R    t        | t        j                        xr | j                  S r2   )rI   r   Graph_building_function)graphs    r,   _IsFunctionr     s      
E399	%	B%*B*BBr.   c                 4    t        |       sJ | j                  S r2   )r   captures)
func_graphs    r,   	_Capturesr     s    	Z	  	 			r.   c                    t        | t        j                        spt        | j                  j
                        rQ| j                  j                  dk(  r8t        | j                  j
                        D ]  \  }}| |u st        |      c S  | S )zIf t is a captured value placeholder, returns the original captured value.

  Args:
    t: Tensor

  Returns:
    A tensor, potentially from a different Graph/FuncGraph.
  Placeholder)	rI   r   EagerTensorr   r*   r   rt   r   _MaybeCaptured)r   input_tplaceholder_ts      r,   r   r     sl     Q
(!$$**!$$))}"<"+ADDJJ"7 '	
m	g&&' 
(r.   c                 v    t        | |      D cg c]  }t        |t        j                        r|! c}S c c}w )a  Returns the inputs of op, crossing closure boundaries where necessary.

  Does not return any captured EagerTensors, i.e., the number of tensors
  returned may be less than the actual number of inputs.

  Args:
    op: Operation
    xs_set: ObjectIdentitySet of Tensors we are differentiating w.r.t.

  Returns:
    A list of tensors. The tensors may be from multiple Graph/FuncGraphs if op
    is in a FuncGraph and has captured inputs.
  )_InputsrI   r   r   )r*   r?   r   s      r,   r:   r:     s,     R(	O
1coo0N!	OO	Os   66c                     t        | j                        r5g }| j                  D ]"  }||vrt        |      }|j	                  |       $ |S | j                  S )a5  Returns the inputs of op, crossing closure boundaries where necessary.

  Args:
    op: Operation
    xs_set: ObjectIdentitySet of Tensors we are differentiating w.r.t.

  Returns:
    A list of tensors. The tensors may be from multiple Graph/FuncGraphs if op
    is in a FuncGraph and has captured inputs.
  )r   r   ru   r   r8   )r*   r?   ru   r   s       r,   r   r     sX     FYY  
&1mmA M99r.   c                     | j                         }|D ]5  }t        |      D ]%  \  }}|| u s|j                  t        ||             ' 7 |S )a  Returns the consumers of t, crossing closure boundaries where necessary.

  Args:
    t: Tensor
    func_graphs: a list of FuncGraphs that may have captured t.

  Returns:
    A list of tensors. The tensors will be from the current graph and/or
    func_graphs.
  )	consumersr   r    r%   )r   r(   r   r   r   placeholders         r,   r%   r%     sZ     kkm) ?d )$ ?	AK=>?? 
r.   	gradientsFc
                   ./0 t        j                         rt        d      t        j                  t        |             } t        |      D 
cg c]%  }
t        j                  |
      r|
j                  n|
' }}
|t        |      }t        d |D              st        d | D              rmt        j                  |      }t        j                  |       }|dnt        j                  |      }t        ||||||||||	
      }t        j                  ||      S |	t        j                         }		 t!        |      }g }|	}t%        |      r)|j'                  |       |j(                  }t%        |      r)|g n
t        |      }|dgt+        |       z  }t        j,                  |dt/        |       t/        |      z   t/        |      z   t/        |      z         5 }t        j                         j1                  d      }t3        j4                  | d	
      } t3        j6                  |dd      }t9        j:                  |      }t=        || ||      }| D cg c]  }|j>                   }}|D cg c]  }|j>                   }}|D cg c]  }|j>                   }}tA        |||||      \  }}}i }tC        | |      D ]  \  }}tE        |||        tG        jH                         }tK               }|D ]9  /|/   dk(  } | s/|vs/|v s|jM                  /       |j'                  /       ; |rf|jO                  ||      }!|!D ]O  }tQ        jR                  |      stE        |||jU                  |             |j'                  |j>                         Q tW        ||||      }"|r|jY                         /t[        /||      5  |r|j]                  /d       t_        |/|||      0|r|ja                  /d       d.d}#tc        /      }$|	je                  /jf                        xs |$}%t        d 0D              }&|&r/|"vr	 t        jh                  /      .|r|j]                  /d       t}        j~                  /      rb/j                  V/j                  j                         r</j                  t        j                         j                         k(  rt        /||       .s|%r|&rt        0      D ]  \  })}*t        |*t        j                        r!|*r$.s|%s#tQ        jR                  /j                  |)         sK|r|j                  /|)      0|)<   ct        j                  /j                  |)         st        j                  /|)      0|)<    t        j,                  /jr                  dz         5  |	j                  /      5  .rt        |/|#./0fd      }+nt        |/|#/0fd      }+t        |+      }+t        |+/       |rrt+        |+D 
cg c]  }
|
|
 c}
      dkD  rTt        j                  d      5  t        j                  d|d      5  t        j                  |+      }+ddd       ddd       ddd       ddd       t        /0+       ndgt+        t        /|            z  }+t        tC        t        /|      |+            D ]  \  })\  },}-|-t        |-t        j                        r=|,j                  t        j                  k7  r 	 |-j                  |,j                                t        |,t        j                        r~tE        ||,|-        |r|ja                  /d       ddd       t        |/||||       |rddd       r|j                          |D 
cg c]  }
t        |
|       c}
S c c}
w # t"        $ r t#        d| d      w xY wc c}w c c}w c c}w # tj        $ r |%r|$rtm        jn                  /jq                  d      jr                        }'|	ju                  |'      }#|#sgtw        |	d      r[|	j(                  }(|(M|(ju                  |'      }#|#n9tw        |(d      r|(j(                  }(nn|(1n|	ju                  /jf                        }#ty        /d|#      }#|#jz                  .n&tk        d/jr                   d/jf                   d      Y w xY wc c}
w # 1 sw Y   xY w# 1 sw Y   xY w# 1 sw Y   xY w# 1 sw Y   xY w# t"        $ r6 t#        d/jr                   d|) d|,j                   d |-j                         w xY w# 1 sw Y   xY w# 1 sw Y   xY wc c}
w )!zImplementation of gradients().z[tf.gradients is not supported when eager execution is enabled. Use tf.GradientTape instead.Nc              3   P   K   | ]  }t        |t        j                           y wr2   rI   r   CompositeTensor)r4   rF   s     r,   r5   z#_GradientsHelper.<locals>.<genexpr>       	Fa*Q(88
9	F   $&c              3   P   K   | ]  }t        |t        j                           y wr2   r   )r4   ro   s     r,   r5   z#_GradientsHelper.<locals>.<genexpr>  r   r   *Unknown value for unconnected_gradients: ''r   uidro   rP   rF   T)rQ   as_refr   beforec              3   X   K   | ]"  }t        |t        j                        xs | $ y wr2   rI   rg   rh   r4   gs     r,   r5   z#_GradientsHelper.<locals>.<genexpr>  s*      
67Jq*++,11
s   (*r   outer_graph__defunz"No gradient defined for operation'z' (op type: a  ). In general every operation must have an associated `@tf.RegisterGradient` for correct autodiff, which this op is lacking. If you want to pretend this operation is a constant in your program, you may insert `tf.stop_gradient`. This can be useful to silence the error in cases where you know gradients are not needed, e.g. the forward pass of tf.custom_gradient. Please see more details in https://www.tensorflow.org/api_docs/python/tf/custom_gradient.F_gradc                        g S r2   r3   )r   r*   r   s   r,   <lambda>z"_GradientsHelper.<locals>.<lambda>  s    1Hi1H r.   c                      t               S r2   )r   )r*   r   s   r,   r   z"_GradientsHelper.<locals>.<lambda>  s    "i1H r.   r6   ignore_existingzWIncompatible shapes between op input and calculated input gradient. Forward operation: z. Input index: z. Original input shape: z#. Calculated input gradient shape: )ar   executing_eagerlyRuntimeErrorr   convert_variables_to_tensorsrM   r   is_resource_variablehandleanyr   get_flat_tensors_for_gradients_GradientsHelper"replace_flat_tensors_for_gradientsr   r   r   rX   r   r8   r   rW   
name_scoperJ   unique_namer
   rY   .internal_convert_n_to_tensor_or_indexed_slicesr   ObjectIdentitySetrp   r*   rG   r[   _SetGradr   r   r7   r"   ProcessUnusedLoopExitsr   r$   ZerosLikeForExitr   r!   r\   EnterGradWhileContext_AggregatedGradsExitGradWhileContextr   _is_functionrt   get_gradient_functionLookupErrorr   as_bytesr   rQ   _get_functionhasattrgetattrpython_grad_funcr   IsSwitch_control_flow_contextIsWhileContext_get_control_flow_contextr   rZ   rI   rg   rh   r#   ZerosLikeV1WhileLoopr   supports_default_gradr   	ZerosLike_original_opr   rx   devicer   r   rK   _LogOpGradientsr   rS   r	   re   	set_shape	get_shapera   r   _UpdatePendingAndEnqueueReadyPostProcessing_GetGrad)1rk   xsrj   rQ   r>   gate_gradientsaggregation_methodstop_gradientsunconnected_gradients	src_graphrF   flat_xsflat_ysflat_grad_ys
flat_gradsr(   
curr_graph
grad_scoperl   r?   r   r/   r&   ry   r@   rE   rD   rw   ro   rO   r)   
to_ops_setready
loop_exitsr}   	func_callis_partitioned_callis_func_callhas_out_grads	func_namer   rn   out_gradr   t_inin_gradr   r*   r   s1                                                 @@@r,   r   r     s	     
 B C C2272;?" r{
 (<<Q?ahhQF"  gG 
	F2	FF		F2	FF'FFrJG'FFrJG!@@I  "'7L$"=~"4n"7DJ %GG
J  %%'IO01FG +*Jz"''J 	J (/2W^5L._fs2wG
~~
K
2hbD004=@B U,EO ((*66u=L		=	=bs	KB		F	F
T
#B..r2FWb*E)+G qaddF !!H!'56!662?5{F3L/mZ E W% !	6ua ! EJ  R A%e	2Z'B2B,BrR 44]JOj !$$Q'
5!Z88;
<
,,qtt

 "3]FKH
==?bL2MN Q<

*
*2d
*
;$UBj%79	

)
)"T
)
:	04 --bgg6M:M 
;D
 
 b0(T//3GP 

*
*2e
*
< &&r*$$0$$335$$!!#==?@
,R6
B | 'y1 Ckax):):;H ,,RZZ]; )>>r1E	!#99"**Q-H  2;;BB	!%C& ~~bgg/0 @''+ @ )R)HJ
 )R)HJ *h'"5CH );q,-M *+ ); %<>?%@ZZ% @66"&*, @  055h?H	@@!@@0 "i
2 Vc'"f"566( #,CF0CX,N"O 	-Ag 7J$5$56

foo-I!!$.."23 dCOO4udG,	- 

)
)"U
)
;cQ<h $E2umZ$*,o {U,n =?	@(5!2
3	@@G4 
 O

45J4K1MO OOL  !6x  &T$"OOBKK,<,A,AB	%33	
 !WY%F#//%) % 3 3I >I -um4#//e ) &33BGG<	 ""i;i!22gggYl277) 	4S
ST T 3&T~);@ @@ @!@ @@ @J   I ::<'' CS 8 E88?HI IIQQ< Q<AU, U,r 
As`  *_/_ A:e:_'#e:)_,<e:_1A%e:;e: e:Ae:A'e:?B e- _6B?e-e-&e-?:e-:=e-7d	Ad	c2d	>dc7-d5d	=dAe-7e-d+6e-$e-5e:/f_$'e:6Bc/Ac/+e-.c//e-2d	7d<dd	d	ddd(#e-+?e*	*e--e7	2e::fc                     t        | |      }|D ]`  }t        |t        j                  t        j
                  f      r y|s2t        |t        j                        sMt        d |D              s` y y)z%Return true iff op has real gradient.Tc              3   $   K   | ]  }|d u 
 y wr2   r3   r   s     r,   r5   z&_HasAnyNotNoneGrads.<locals>.<genexpr>  s     -qQd]-s   F)		_GetGradsrI   rg   rh   r
   rf   r   Sequencer   )rw   r*   r   r%  s       r,   _HasAnyNotNoneGradsr,    sc    r") h(Z..0L0LMNJx)A)AB	-H-	- 
r.   c           	         t        ||      D ]  }||j                  xx   dz  cc<   ||j                     dk(  }|r5|s3||j                     dkD  xr t        j                  |j                        }|sgt        j                  |j                        rN|j                  |j                  d      }|j                  j                  |       |xj                  dz  c_        |j                  dk(  sd}	|j                  D ]Q  }
t        | |
j                        rd}	|j                  |
j                         7|j                  j                  |
       S |	r_|j                  D ]N  }
t        j                  |
      rt        | |
|j                  |
             |j                  |
j                         P |j                  D ]  }
|j                  |
j                          |j                  |j                          y)z@Update pending count for the inputs of op and enqueue ready ops.r6   r   Fr   TN)r:   r*   r   IsLoopSwitch
IsLoopExitGetGradStatedeferred_exitsr8   pending_exits_countr,  unused_exitsr   r$   r   r   )rw   r*   r)   rE   rD   r?   rF   r  
grad_statehas_not_none_gradro   s              r,   r  r    s    2v&  a!$$1!$$1$E%ADD!A%N*;*H*H*Ne		%	%add	+,,QTT%,@
!!((+&&!+&))Q.#
,, 0a"5!$$/"&ll144 %%,,Q/0   ,, !**1-:#>#>q#ABll144 !  ,, !ll144 ! 	QTTA r.   c                 Z   |j                   }| j                  |      }|s0t        t        |j                              D cg c]  }g  }}|| |<   ||j
                     }t        |t              r|j                  |       yt        j                  |      sJ |||j
                  <   yc c}w )z/Sets gradient "grad" in "grads" for tensor "t".N)r*   getrangerW   r#   value_indexrI   rJ   r8   r   r.  )rw   r   gradr*   op_gradsr   t_gradss          r,   r   r   B  s    tt"YYr](	!#bjj/23q3H3E"IQ]]#'NN4))"---"HQ]] 4s    	B(c                     t        j                  |       }| j                  t        j                  k(  r*t        j                  t        j                  |       |      S t        j                  | |      S )N)rS   )
r   r   rS   r	   re   r   zerosr   variable_shape
zeros_like)r   t_dtypes     r,   
_ZerosLikerB  Q  sZ    ,,Q/'WW??,,Q/w@ @ 11r.   c                 R   |j                   }| j                  |      }|sA|t        j                  k(  rt	        |      S |t        j
                  k(  ryt        d| d      ||j                     }|t        j                  k(  r|t	        |      S t        |t              rJ d       |S )zGets gradient for tensor "t".Nr   r   z2gradients list should have been aggregated by now.)
r*   r7  r   ZEROrB  NONErX   r9  rI   rJ   )rw   r   r  r*   r;  t_grads         r,   r  r  Z  s    tt"YYr](	 4 9 99]	"6";";	;67L6MQ
OQ Q AMM"&2777FNa=d LJL 
	-r.   c                 v    || v r| |   S t        t        |j                              D cg c]  }g  c}S c c}w )zGets all gradients for op.)r8  rW   r#   )rw   r*   r   s      r,   r*  r*  q  s4    5[9c"**o./1B///s   	6c                     t        j                         }| D ]<  }t        |t        j                        s|j                  |j                               }> |S r2   )r   unknown_shaperI   rg   rh   
merge_withr  )ru   ra   rn   s      r,   _AccumulatorShaperK  y  sL    

$
$
&% .a!Z&&'q{{}-e. 
,r.   c                    t        j                  dd| j                  z   dz          d t        j                  dddj                  fd|D                     t        j                  dddj                  fd	|D                     y
)z"Log the in and out grads of an op.r6   zGradient for 'r   c                 L    | yt        | t        t        f      rt        |       S y)NFT)rI   rJ   rK   boolrL   s    r,   _FilterGradz$_LogOpGradients.<locals>._FilterGrad  s$    y!dE]#!Wnr.   z  in  --> %sz, c              3   H   K   | ]  } |      s|j                     y wr2   rP   r4   rF   rO  s     r,   r5   z"_LogOpGradients.<locals>.<genexpr>  s     EAk!nE   ""z  out --> %sc              3   H   K   | ]  } |      s|j                     y wr2   rP   rQ  s     r,   r5   z"_LogOpGradients.<locals>.<genexpr>  s     DA[^DrR  N)loggingvlogrQ   join)r*   r   r   rO  s      @r,   r  r    sm    	,,q"RWW,s23 
,,q.yyEEEG	,,q.yyDDDFr.   c                    t        j                  d       }| D ]   }||j                     j                  |       " g }d }t	        ||      D ]Y  }||   }t        j                  |d   j                  |d      5  |j                  t        j                  |             ddd       [ t        j                  |      S # 1 sw Y   zxY w)z/Adds tensors from potentially multiple devices.c                      g S r2   r3   r3   r.   r,   r   z"_MultiDeviceAddN.<locals>.<lambda>  s    b r.   c                     | dS | S )N r3   )devs    r,   	DeviceKeyz#_MultiDeviceAddN.<locals>.DeviceKey  s    2%#%r.   )keyr   Tr   N)
r   r<   r
  r8   sortedr   r   r*   r   add_n)tensor_listrl   tensors_on_devicer   summandsr\  r[  tensorss           r,   _MultiDeviceAddNrd    s     "--j9 4ffmm$++F34 (& %95 /c$G		(	(

 / oohnnW-.	/ // 
	!!/ /s   ;%B??C	AggregationMethodc                        e Zd ZdZdZeZdZdZy)re  a  A class listing aggregation methods used to combine gradients.

  Computing partial derivatives can require aggregating gradient
  contributions. This class lists the various methods that can
  be used to combine gradients in the graph.

  The following aggregation methods are part of the stable API for
  aggregating gradients:

  *  `ADD_N`: All of the gradient terms are summed as part of one
     operation using the "AddN" op (see `tf.add_n`). This
     method has the property that all gradients must be ready and
     buffered separately in memory before any aggregation is performed.
  *  `DEFAULT`: The system-chosen default aggregation method.

  The following aggregation methods are experimental and may not
  be supported in future releases:

  * `EXPERIMENTAL_TREE`: Gradient terms are summed in pairs using
    the "AddN" op. This method of summing gradients may reduce
    performance, but it can improve memory utilization because the
    gradients can be released earlier.
  * `EXPERIMENTAL_ACCUMULATE_N`: Same as `EXPERIMENTAL_TREE`.

  Example usage when computing gradient:

  >>> @tf.function
  ... def example():
  ...   x = tf.constant(1.0)
  ...   y = x * 2.0
  ...   z = y + y + y + y
  ...   return tf.gradients(z, [x, y],
  ...     aggregation_method=tf.AggregationMethod.EXPERIMENTAL_ACCUMULATE_N)
  >>> example()
  [<tf.Tensor: shape=(), dtype=float32, numpy=8.0>,
   <tf.Tensor: shape=(), dtype=float32, numpy=4.0>]

  r   r6      N)__name__
__module____qualname____doc__ADD_NDEFAULTEXPERIMENTAL_TREEEXPERIMENTAL_ACCUMULATE_Nr3   r.   r,   re  re    s     %L %'r.   c                 "   |t         j                  }t         j                  t         j                  t         j                  g}||vrt        d| d| d      t        | |      }t        |      D ]  \  }}|rBt        |t        j                  t        j                  f      rt        j                  |      sJ Kt        |t        j                         r$t#        d |D              st%        d| d| d      |r t'        |      d	k  rd
}	|d   ||<   t#        d |D              rt)        |      }
|t         j                  t         j                  fv rYd}	t+        j,                  |j.                  dz         5  |d   }|dd D ]  }t1        j2                  ||g      } |||<   ddd       nd}	t5        ||      ||<   t7        j8                  d	dt'        |      |
|	       rt;        j<                  |      ||<   d||<    |S # 1 sw Y   QxY w)a  Get the aggregated gradients for op.

  Args:
    grads: The map of memoized gradients.
    op: The op to get gradients for.
    gradient_uid: A unique identifier within the graph indicating
      which invocation of gradients is being executed. Used to cluster
      ops for compilation.
    loop_state: An object for maintaining the state of the while loops in the
                graph. It is of type ControlFlowState. None if the graph
                contains no while loops.
    aggregation_method: Specifies the method used to combine gradient terms.
      Accepted values are constants defined in the class `AggregationMethod`.

  Returns:
    A list of gradients, one per each output of `op`. If the gradients
      for a particular output is a list, this function aggregates it
      before returning.

  Raises:
    TypeError: if the incoming grads are not Tensors or IndexedSlices.
    ValueError: if the arguments are invalid.

  Nz'Invalid `aggregation_method` specified z. Accepted values are .c              3   t   K   | ]0  }|,t        |t        j                  t        j                  f       2 y wr2   )rI   rg   rh   r
   rf   r   s     r,   r5   z#_AggregatedGrads.<locals>.<genexpr>  s7      C= 	1z((.*F*FGHCs   68zInvalid gradient z
 [index = z?]. Gradients have to be either all Tensors or all IndexedSlicesrg  nopr   c              3   V   K   | ]!  }|t        |t        j                         # y wr2   r   r   s     r,   r5   z#_AggregatedGrads.<locals>.<genexpr>  s(      O/0*Q
))
*Os   ))tree_gradient_sumr6   r_  z#  _AggregatedGrads %d x %s using %s)re  rm  rl  rn  ro  rX   r*  rZ   rI   rg   rh   r
   rf   r   r.  r   r+  allr^   rW   rK  r   r   rQ   r   r_  rd  rT  rU  r   AggregateIndexedSlicesGradients)rw   r*   rl   rD   r  valid_aggregation_methodsr   rn   r%  usedr   running_sumr:  s                r,   r   r     sR   : *220BB113 88

12D1E F89	<= = r")y) /ka	
Z&&(D(DE
G --b1118_556s CC @ )(:aS AK K L L 	X	{	! O4<O O(2//77"
 
 $~~bgg78 '"1+K  @$NNK+>?k@&IaL	' ' $)(LA)A,Q=s8}!4	) %DDXN	! il_/` 
' 's   7,HH	r6   rg  c                 ,    t        j                  |       S )z=Determines whether and how `args` may require tape gradients.)r   #TFE_Py_TapeSetPossibleGradientTypes)rc  s    r,   PossibleTapeGradientTypesr~  ?  s    		7	7	@@r.   )__unsupported__r2   )Nrk  r   
contextlibtensorflow.core.frameworkr   tensorflow.pythonr   tensorflow.python.eagerr   r   tensorflow.python.frameworkr   r   r	   r
   r   r   rg   r   tensorflow.python.opsr   r   r   r   r   r   r   r   +tensorflow.python.ops.unconnected_gradientsr   tensorflow.python.platformr   rT  tensorflow.python.utilr   r   r   tensorflow.python.util.compatr    tensorflow.python.util.tf_exportr   r-   rJ   	OperationrG   rM   rp   rx   r   contextmanagerr\   r   r   r   r   r   r   r   r:   r   r%   rE  r   r,  r  r   rB  r  r*  rK  r  rd  re  r   POSSIBLE_GRADIENT_TYPES_NONE#POSSIBLE_GRADIENT_TYPES_FIRST_ORDER$POSSIBLE_GRADIENT_TYPES_HIGHER_ORDERr~  r3   r.   r,   <module>r     sX   D   4 ( 1 + 8 A . 6 + < 4 + 2 4 3 2 4 * 7 L < ) 2 1 9 68(B5B53==!B5J4 !2l^ .$3==!$CMM*$N 



 

N3== N "S]] "JOO3==!O6C
&P P& 6* "%16$)(,$(+?+D+D#RAj	3== 	$}}$N#2.0 0F F$"8 +  +   + d )-	Wx  ! &' #'( $Ar.   