
    BVh2                         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 Z G d	 d
e      Zd Zd Zd Zd Zej(                  d        Zd Zd Zy)zSubscribe function.    N)ops)tensor)	array_ops)	variables)
tf_loggingc                    t        |       }t        | t        j                        r |       S t        | t        j
                        r | j                               S t        | t        t        f      rD| D cg c]  }t        |       } }|t        u rt        |       S |t        u rt        |       S  ||  S |t        u r"t        fd| j                         D              S t        d| d|      c c}w )aH  Helper method to recursively apply a function to structure of tensors.

  The structure of the tensors should take the form similar to fetches in
  `tf.compat.v1.Session` and includes single `Tensor`, `list`, nested `list`,
  `tuple`,
  `namedtuple`, or `dict`.

  Args:
    tensors: Single `Tensor`, `list`, nested `list, `tuple`, `namedtuple`, or
      `dict`.
    apply_fn: Function to apply to each `Tensor` and should return a `Tensor`.

  Returns:
    Returns the modified tensors with the same structure.
  Raises:
    `TypeError` if undefined type in the tensors structure.
  c              3   @   K   | ]  \  }}|t        |      f  y wN)_recursive_apply).0kvapply_fns      U/home/dcms/DCMS/lib/python3.12/site-packages/tensorflow/python/framework/subscribe.py	<genexpr>z#_recursive_apply.<locals>.<genexpr>:   s"     Otq!$Q12Os   z_recursive_apply argument z has invalid type )type
isinstance
tensor_libTensorr   Variablevaluelisttupler   dictitems	TypeError)tensorsr   tensors_typets    `  r   r   r      s    $ g,**+G'9--.GMMO$$'D%=)6=>8,>G>t']		7^!!tOw}}OOO
0;M#&( ) ) ?s   9C4c                   (    e Zd ZdZdgZd Zd Zd Zy)_ControlOutputCachezHHelper class to manage calculating and caching control_outputs in graph.cachec                     i | _         y r
   )r"   )selfs    r   __init__z_ControlOutputCache.__init__E   s	    DJ    c                     i }|j                         D ]8  }|j                  D ]'  }||vrt               ||<   ||   j                  |       ) : |S )zReturns the map of control_outputs for a given graph.

    Args:
      graph: The graph to parse.

    Returns:
      A map of the control outputs.
    )get_operationscontrol_inputssetadd)r$   graphcontrol_outputsopcontrol_inputs        r   calc_control_outputsz(_ControlOutputCache.calc_control_outputsH   se     O""$ /,, /-/+.5/-
(&**2.//
 r&   c                     |j                   | j                  vr5| j                  |j                         }|| j                  |j                   <   n| j                  |j                      }|j                  |g       S )zReturn the control outputs for a given op.

    Args:
      op: The op to fetch control outputs for.

    Returns:
      Iterable of control output ops.
    )r,   r"   r0   get)r$   r.   r-   s      r   get_control_outputsz'_ControlOutputCache.get_control_outputsY   s_     
xxtzz!11"((;o,djj

288,or2&&r&   N)__name__
__module____qualname____doc__	__slots__r%   r0   r3    r&   r   r!   r!   @   s    Pi)"'r&   r!   c                 :   g }t        | j                               D ]7  }|j                  |t        |j                        j	                  |       f       9 |j                  | j                        }| j                  j                  dz   }t        j                  |      5  g }|D ]  }| ||       z  } t        j                  |      5  t        j                  |       }	ddd       ddd       |D ]  \  }}
|j                  |
	        |D ]s  }|j                  }| j                  |v r|j                  | j                         |j                  	j                         |j!                          |j#                  |       u 	S # 1 sw Y   xY w# 1 sw Y   xY w)al  Helper method that subscribes a single tensor to a list of side_effects.

  Args:
    tensor: `tf.Tensor`
    side_effects: List of side_effect functions see subscribe for details.
    control_cache: `_ControlOutputCache` helper to get control_outputs faster.

  Returns:
    The modified replacement to the passed in tensor which triggers the side
    effects.
  /subscription/N)r   	consumersappendinputsindexr3   r.   namer   
name_scopecontrol_dependenciesr   identity_update_inputr)   remove_remove_all_control_inputs_add_control_inputs)r   side_effectscontrol_cacheupdate_inputconsumer_opupdate_control_inputrA   outssoutr?   new_control_inputss               r   _subscribe_newrQ   j   s    ,&**,- Okd;+=+=&>&D&DV&LMNO '::699E yy~~ 00*
~~j! 'D 
aid 
	!	!$	' 'v&c'' ) *k5eS)* * 8k
 %33yy&&		*cff%**,##$678 
*'' '' 's$   *F	FFF	
FFc                 *   t        | j                  j                        dk(  s*J dj                  | j                  j                               | j                  j                  d   }g }|j                  j                  dz   }t        j                  |      5  |D ]  }| ||      z  } 	 ddd       |D cg c]*  }t        |t        j                        r|j                  n|, }}| j                  j                  |       | S # 1 sw Y   [xY wc c}w )a  Helper method to extend the list of side_effects for a subscribed tensor.

  Args:
    tensor: A `tf.Tensor` as returned by subscribe().
    side_effects: List of side_effect functions, see subscribe for details.

  Returns:
    The given subscribed tensor (for API consistency).
     Op {} must only have one inputr   r;   N)lenr.   r>   formatr@   r   rA   r   r   r   rG   )r   rH   source_tensorrM   rA   rN   rO   out_opss           r   _subscribe_extendrY      s    
VYY	!	# %E%L%Liinn& 	#))""1%- 
$$$'77*
~~j!  
ad
 HL@C
3
 1 12cff;'  	))(	- s   D6/DDc                    | j                   j                  dk7  ryt        j                  d| j                        }|t        |j                               dk7  ry|j                  d      }t        | j                   j                        dk(  s*J dj                  | j                   j                               | j                   j                  d   }||j                   j                  k7  ryy)	af  Checks if the given tensor is an identity op returned by `subscribe()`.

  Args:
    tensor: A `tf.Tensor` to check.

  Returns:
    True if the given tensor matches the criteria for subscription identities:
    its op type is `Identity`, its name matches the name of its input and
    conforms to the convention for subscribed nodes.
    False otherwise.
  IdentityFz0(?P<prefix_name>^.*?)/subscription/Identity[^/]+rS   prefix_namerT   r   T)
r.   r   rematchr@   rU   groupsgroupr>   rV   )r   r^   r\   rW   s       r   _is_subscribed_identityra      s     YY^^z! ((F;; %
]c%,,.)Q.M*+ 
VYY	!	# %E%L%Liinn& 	#))""1%-M$$)))	r&   c                 |   | j                   j                  s;t        j                  dj	                  | j
                  | j                                | S t        |       rt        | |      S | j                  j
                  dz   }| j                         }|D cg c]   }|j
                  j                  |      s|" }}t        |      dk  s*J dj	                  | j                  j
                               t        |      dk(  r)|d   j                  d   }t        |      rt        ||      S t        | ||      S c c}w )a  Helper method that subscribes a single tensor to a list of side_effects.

  This method will check if the given tensor has already been subscribed or if
  it's a tensor returned by a previous call to `subscribe()` and, if so, will
  reuse the existing identity op, appending the given side effects to the list
  of existing ones.

  Args:
    tensor: The `tf.Tensor` to be subscribed.
    side_effects: List of side_effect functions, see subscribe for details.
    control_cache: `_ControlOutputCache` helper to get control_outputs faster.

  Returns:
    The modified replacement to the passed in tensor which triggers the side
    effects or the given tensor, if it was already been subscribed.
  z?Tensor {} has an un-supported {} type and cannot be subscribed.z/subscription/IdentityrS   z8Op {} must only have one subscription op connected to itr   )dtypeis_numpy_compatibleloggingdebugrV   r@   ra   rY   r.   r<   
startswithrU   outputsrQ   )r   rH   rI   rA   r<   r.   matching_opscandidate_tensors           r   
_subscriberk      s   & 
	)	)MM !"(&fll"CEMV$V\22 yy~~ 88* )(KBGG,>,>z,J"K,K	\	a	 O #78>vyy~~8NO	!#A..q1/0/>>	m	<< Ls    D97D9c              #      K   | j                   j                         }|r|j                          	 d |r|j                          yy# |r|j                          w w xY ww)a  Preserve the control flow context for the given tensor.

  Sets the graph context to the tensor's context so that side effect ops are
  added under the same context.

  This is needed when subscribing to tensors defined within a conditional
  block or a while loop. In these cases we need that the side-effect ops
  are created within the same control flow context as that of the tensor
  they are attached to.

  Args:
    tensor: tensor whose context should be preserved.

  Yields:
    None
  N)r.   _get_control_flow_contextEnterExit)r   contexts     r   _preserve_control_flow_contextrq     sP     ( II//1'MMO	lln wlln s   -A A A AA c                     t        j                  | j                        5  t        |       5  t        | ||      cddd       cddd       S # 1 sw Y   nxY w	 ddd       y# 1 sw Y   yxY w)ae  Helper method that subscribes a single tensor to a list of side_effects.

  This is a thin wrapper around `_subscribe` and ensures that the side effect
  ops are added within the same device and control flow context of the
  subscribed tensor.

  Args:
    tensor: The `tf.Tensor` to be subscribed.
    side_effects: List of side_effect functions, see subscribe for details.
    control_cache: `_ControlOutputCache` helper to get control_outputs faster.

  Returns:
    The modified replacement to the passed in tensor which triggers the side
    effects or the given tensor, if it was already been subscribed.
  N)r   devicerq   rk   )r   rH   rI   s      r   _scoped_subscribert   "  sf    " zz&--  =	'	/ =m<= == == = == = =s!   A"A	A"A	A""A+c                 \    t        d      sgt               t        | fd      }|S )a  Subscribe to a tensor.

  This method will attach side effect graphs to a given set
  of tensors. Set of tensors follows from session.run and supports
  single `Tensor`, `list`, nested `list`, `tuple`, `namedtuple`, or `dict`. It
  returns the tensors in the same passed in structure, but as clones with
  side effects applied. The supplied side effect graphs are specified
  as a constructor function which takes the target tensor and
  constructs a side effect graph and returns a list of ops that should
  be control dependencies on fetching the tensor. It will append
  'subscription' to the name scope of the tensor for every node in
  the side effect graph. These control dependencies are what trigger
  the side effects. Subscribe will construct the additions to your
  graph and return the created identity tensor downstream of the control
  dependencies. Use these tensors as you would normally in the rest of
  your tensorflow code. If a given tensor has already been subscribed or a
  tensor returned by a call to subscribe is passed, the previously created
  identity tensor will be reused and the side effect graphs will be added to
  the existing ones.

  Args:
    tensors: `Tensor` or set of tensors to subscribe to. Set of tensors format
      follows from `Session.run` and supports single `Tensor`, `list`, nested
      `list`, `tuple`, `namedtuple`, or `dict`.
    side_effects: Function(s) that takes a `Tensor`, construct a subgraph, and
      return a nonempty list of control dependencies. This can be a single
      function or list of functions.

  Returns:
    Subscribed tensors, which are identity copies of the passed in tensors
      in the same passed in structure, but the graph has been modified
      such that these are downstream of the control dependencies for
      the side effect graphs. Use these functionally equivalent tensors
      instead of the passed in tensors for further construction or running.
  __iter__c                     t        |       S r
   )rt   )r   r-   rH   s    r   <lambda>zsubscribe.<locals>.<lambda>a  s    *1lOL r&   )hasattrr!   r   )r   rH   resultr-   s    ` @r   	subscriber{   8  s5    H 
z	* >L')/LN&	-r&   )r7   
contextlibr]   tensorflow.python.frameworkr   r   r   tensorflow.python.opsr   r   tensorflow.python.platformr   re   r   objectr!   rQ   rY   ra   rk   contextmanagerrq   rt   r{   r9   r&   r   <module>r      sm      	 + < + + <")J''& ''T,^<D'=T  <=,*r&   