
    AVhn                     t    d Z ddl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gZd Zd	 Zd
 Zd Zd Zy)z/Utilities for slicing in to a `LinearOperator`.    N)dtypes)tensor_util)	array_ops)nestbatch_slicec                     | ||g}|D cg c]  }t        j                  |       }}t        d |D              r|\  }}}t        j                  |||      S t        j                  | ||      S c c}w )Nc              3   $   K   | ]  }|d u 
 y wN ).0args     T/home/dcms/DCMS/lib/python3.12/site-packages/tensorflow/python/ops/linalg/slicing.py	<genexpr>z'_prefer_static_where.<locals>.<genexpr>"   s     2SD2s   )r   constant_valueallnpwherer   )		conditionxyargsaconstant_args
condition_x_y_s	            r   _prefer_static_wherer      sr    
Q	$:>?Q;--a0?-?2M22&JB88JB''	Aq	)) @s   A.c           	      $   t        | d      ri }| j                  j                         D ]E  \  }}t        | |      }t	        j
                  |t        j                  t        |      ||      ||<   G t        | j                  fi |} t        |       di |S t        j                  |t        j                  |gt        j                         gd      }t        j"                  | t        j$                  |t        j&                  |                   S )z;Broadcasts `param` with the given batch shape, recursively.batch_shape_tensor)batch_shape)dtyper   )axisr   )hasattr-_experimental_parameter_ndims_to_matrix_ndimsitemsgetattrr   map_structure_up_to	functoolspartial%_broadcast_parameter_with_batch_shapedict
parameterstyper   concatonesr   int32broadcast_tobroadcast_dynamic_shapeshape)	paramparam_ndims_to_matrix_ndimsr    override_dictnamendims	sub_paramr,   
base_shapes	            r   r*   r*   (   s    U()MJJPPR :e%&i 44
Y&&3%'(15:mD: e&&8-8J4;$$$INN&
'v||= >DEG* 
		''
IOOE4JK
M M    c                 ,   g }d}| D ]	  }|t         u rN|dk  rt        dj                  |             t        d | | j	                  t               dz   d D              }| }n|t
        j                  u rn||   ||   kD  }t        |t              r_|j                  |j                  |j                  }
}	}|t        |d|      }|	t        |d|	      }	|
t        |d|
      }
t        ||	|
      }nt        |d|      }|dz  }|j                  |        |S )a  Restricts slices to avoid overflowing size-1 (broadcast) dimensions.

  Args:
    slices: iterable of slices received by `__getitem__`.
    intended_shape: int `Tensor` shape for which the slices were intended.
    deficient_shape: int `Tensor` shape to which the slices will be applied.
      Must have the same rank as `intended_shape`.
  Returns:
    sanitized_slices: Python `list` of slice objects.
  r   z!Found multiple `...` in slices {}c              3   @   K   | ]  }|t         j                  u  y wr
   )r   newaxis)r   ss     r   r   z#_sanitize_slices.<locals>.<genexpr>P   s       -,)*!9$$
$-,s      N)Ellipsis
ValueErrorformatsumindexr   r>   
isinstanceslicestartstopstepr   append)slicesintended_shapedeficient_shapesanitized_slicesidxslc num_remaining_non_newaxis_slicesis_broadcastrH   rI   rJ   s              r   _sanitize_slicesrT   ?   s=    	# !c
h	q<CCFKLL), -,.4ll8$q()/+-, *,& .-c		!!	!
#C(?3+??l	C	IIsxxTt&|Q>%%lAt<$%lAt<$E4&"<C8	QhcC 3!4 
r;   c                    t        | |t        j                  |            } t        | d      r| j	                         }nt        j
                  |       }t        j                  |      }|d||z
   }t        j                  t        j                  |            dk7  r-t        j                  t        j                  |            dk(  r| S t        |||      }|dkD  rSt        |D cg c]  }t        j                  |      r| c}vr|j                  t               |t        d      g|z  z  }| j                  t        |            S c c}w )a  Slices into the batch shape of a single parameter.

  Args:
    param: The original parameter to slice; either a `Tensor` or an object
      with batch shape (LinearOperator).
    param_ndims_to_matrix_ndims: `int` number of right-most dimensions used for
      inferring matrix shape of the `LinearOperator`. For non-Tensor
      parameters, this is the number of this param's batch dimensions used by
      the matrix shape of the parent object.
    slices: iterable of slices received by `__getitem__`.
    batch_shape: The parameterized object's batch shape `Tensor`.

  Returns:
    new_param: Instance of the same type as `param`, batch-sliced according to
      `slices`.
  r   Nr   )rM   rN   )r*   r   	ones_liker#   r   r3   sizer   r   rT   rA   	is_tensorrK   rG   __getitem__tuple)r4   r5   rL   r    param_batch_shapeparam_batch_rankparam_slicesrQ   s           r   _slice_single_paramr^   i   s<   & 0()*=*=k*JL% U()002!.^^$56'7669
   !<=B  0A!BCqHL![:KM, !1$A[%:%:3%?A A(#U4[M$???L			5.	//	As   $E?Ec           	         t        |t        j                  j                        s|f}t	        |      dk(  r|d   t
        u ri }nx| j                         }i }| j                  j                         D ]I  \  }}t        | |      }|t        j                  |t        j                  t        ||      ||      ||<   K |j                  |       t!        | j"                  fi |} t%        |       di |S )a[  Slices `linop` along its batch dimensions.

  Args:
    linop: A `LinearOperator` instance.
    params_overrides: A `dict` of parameter overrides.
    slices: A `slice` or `int` or `int` `Tensor` or `tf.newaxis` or `tuple`
      thereof. (e.g. the argument of a `__getitem__` method).

  Returns:
    new_linop: A batch-sliced `LinearOperator`.
  r@   r   )rL   r    r   )rF   collectionsabcSequencelenrA   r   r$   r%   r&   r   r'   r(   r)   r^   updater+   r,   r-   )	linopparams_overridesrL   r6   r    
param_namer5   r4   r,   s	            r   r   r      s     
FKOO44	5YF[A&)x/M**,KM383f3f3l3l3n 0/
/eZ(e		$($<$<9$$#FM.%0j!	0 '(E$$66*	e	"z	""r;   )__doc__r`   r(   numpyr   tensorflow.python.frameworkr   r   tensorflow.python.opsr   tensorflow.python.utilr   __all__r   r*   rT   r^   r   r   r;   r   <module>rn      sD    6    . 3 + ' /*M.'T/0d#r;   