o
    Ei<                     @   s   d dl Z d dlZddlmZ d dlZd dlmZmZm	Z	 d dl
mZ e jdd ddddddd	d
dZe jddddZe jje jdd ddddi ddede jdededee jedf dede	dejfddZdS )    N   )util)CallableUnionMappingc                        fddS )Nc                    s"    | fdd|D |fi |S )Nc                       g | ]} |qS  r	   .0xtr	   I/home/ubuntu/veenaModal/venv/lib/python3.10/site-packages/einx/op/vmap.py
<listcomp>       .<lambda>.<locals>.<lambda>.<locals>.<listcomp>r	   )exprs_in
tensors_in	exprs_outkwargscr   r	   r   <lambda>
   s
    <lambda>.<locals>.<lambda>r	   r   r   r	   r   r   r   
       r   )traceF)flatbackendopr   verbosec                   s  
d u ri 
t t |krtdt  dt | tt| D ]}| D ]}	t|	tjjjr8tdq*q$fddt	|D }
|}retd tddd D  td	d
d |D  tj|d\}
}t|}tdd |
D sJ tdd |D sJ rtd tddd |
D  td	dd |D  dd D dd |D dd |
D dd |D rtd stddd D  td	dd D  tddd D  tddd D  tjdd D d|d
f	d d!
}d"d |
D }d#d$ |
D   fd%d&	d'd( }g }t|
D ]}|D ]|rAj|vrA|j q.q*rOtd)|  t|
t| D ]!}|D ]j|v pf	|krutd*j d+q[qW	fd,d|D }d-d |D }rtd.d/d |D  td0| td1| g }td2d |
D }td3d |D }t|D ]tfd4d|D }tfd5d|D }rtd6 d7| d8|  t	||D ]\}}|d u rtd9 d:| d;q|||||f d<d= tfd>dt	||D }tfd?dt	||D }|| D ]}|v r4| |v r>| q(rMtd@| dA|  qt|D ]\}}}}j|||||dB}qSrrtdCdDd |D  tjj||tdEd |D dF}rt	||D ]\}}	tdG|j|	 qfdHdt	|||D }rtdI t	||D ]\}}	tdJtj||	 qtj|||d}rtdKdLd |D  ||fS )MN	Expected z input tensor(s), got zConcatenation not allowedc                    s$   g | ]\}}t jj||j d qS )r   )einxtracercall_factoryshape)r   tensorexprr#   r	   r   r   #   s    zvmap_stage3.<locals>.<listcomp>zExpressions:z    IN:c                 S      g | ]}t |qS r	   strr   er	   r	   r   r   +   r   z    OUT:c                 S   r*   r	   r+   r-   r	   r	   r   r   ,   r   r#   c                 s       | ]
}t jj|V  qd S Nr$   r)   stage3is_flatr   r)   r	   r	   r   	<genexpr>1       zvmap_stage3.<locals>.<genexpr>c                 s   r/   r0   r1   r4   r	   r	   r   r5   2   r6   zFlat expressions:c                 S   r*   r	   r+   r-   r	   r	   r   r   6   r   c                 S   r*   r	   r+   r-   r	   r	   r   r   7   r   c                 S      g | ]	}t jj|qS r	   r$   r)   r2   
get_markedr4   r	   r	   r   r   :       c                 S   r7   r	   r8   r4   r	   r	   r   r   ;   r:   c                 S   r7   r	   r8   r4   r	   r	   r   r   <   r:   c                 S   r7   r	   r8   r4   r	   r	   r   r   =   r:   zExpressions used in op:c                 S   r*   r	   r+   r-   r	   r	   r   r   B   r   c                 S   r*   r	   r+   r-   r	   r	   r   r   C   r   z    IN_FLAT:c                 S   r*   r	   r+   r-   r	   r	   r   r   D   r   z    OUT_FLAT:c                 S   r*   r	   r+   r-   r	   r	   r   r   E   r   c                 S      g | ]	}t j|jqS r	   r$   r%   Tensorr'   r4   r	   r	   r   r   G   r:   )args)r    c              
      sH  
rt ddd |D  t ddd |D  t|tks J sBtj|d}
r7t ddd |D  t|tksAJ n|}sHnt| trUt| } nt| tjj	se|   fd	d
} | |i 	}t|t
tfsv|f}t|tkrtdt dt| tdd |D rtddd |D  
rt d t|D ]\}}t d||j qtt|D ]!\}\}}tj||jkrtd|j d| dtj| qstj|d\}}
rt ddd |D  |ksJ dd |D  ddd D   
r t ddd |D  t
|S )Nz&Flat input tensors that arrived in op:c                 S      g | ]
}t tj|qS r	   r,   r$   r%   	get_shaper   ar	   r	   r   r   L       z+vmap_stage3.<locals>.op.<locals>.<listcomp>z Input types to vmapped function:c                 S   r*   r	   typer   r   r	   r	   r   r   N   r   r#   z Unflattened input tensors in op:c                 S   r?   r	   r@   rB   r	   r	   r   r   X   rD   c                     s@   t jj | |tdkrdd D dS t jd jdS )Nr   c                 S   r;   r	   r<   r4   r	   r	   r   r   g   r:   z=vmap_stage3.<locals>.op.<locals>.<lambda>.<locals>.<listcomp>r   )r>   r   output)r$   r%   applylenr=   r'   )r>   r   concrete_opexprs_out_expectedr	   r   r   c   s    z)vmap_stage3.<locals>.op.<locals>.<lambda>r"   z1 output tensor(s) from vmapped function, but got c                 s   s     | ]}t |tjj V  qd S r0   )
isinstancer$   r%   r=   rG   r	   r	   r   r5   u   s    z*vmap_stage3.<locals>.op.<locals>.<genexpr>z0Expected tensors from vmapped function, but got c                 S   r*   r	   rE   rG   r	   r	   r   r   x   r   z!Unflattened output tensors in op:    zExpected output shape z from z5-th (zero-based) output of vmapped function, but got zFlattened output tensors in op:c                 S   r?   r	   r@   rB   r	   r	   r   r      rD   c                 S   r*   r	   r+   r   sr	   r	   r   r      r   z != c                 S   r*   r	   r+   rP   r	   r	   r   r      r   z&Returning types from vmapped function:c                 S   r*   r	   rE   rG   r	   r	   r   r      r   )printrJ   r   	unflattenrN   r,   getattrr$   r%   Tracertuplelist
ValueErroranyzipr'   	enumeraterA   flatten)r    tensors_in_flatr   tensors_outexpr_out
tensor_outiexprs_out_funcargs_flat2)	r   r   exprs_in_funcargsexprs_in_funcargs_flatexprs_out_funcargsexprs_out_funcargs_flatr   r   r!   rK   r   r    G   s   
	

zvmap_stage3.<locals>.opc                 S      g | ]	}d d |D qS )c                 S      g | ]}|j qS r	   namerB   r	   r	   r   r          *vmap_stage3.<locals>.<listcomp>.<listcomp>r	   r   rootr	   r	   r   r      r:   c                 S   s   h | ]
}|D ]}|j qqS r	   ri   )r   rn   rC   r	   r	   r   	<setcomp>   rD   zvmap_stage3.<locals>.<setcomp>c                    s*   t | tjjjo| j votjj|  S r0   )rN   r$   r)   r2   Axisrj   	is_markedr)   )axes_names_in_setr	   r   is_broadcast_axis   s
   z&vmap_stage3.<locals>.is_broadcast_axisc                 S   s   t jj|  S r0   )r$   r)   r2   rq   rr   r	   r	   r   
is_vmapped   s   zvmap_stage3.<locals>.is_vmappedzVmapping the following axes: zAxis z( appears both as vmapped and non-vmappedc                    s   g | ]
}t jj| qS r	   )r$   r)   r2   remover4   )rt   r	   r   r      s    c                 S   rg   )c                 S   rh   r	   ri   rB   r	   r	   r   r      rk   rl   r	   rm   r	   r	   r   r      s    z*Flat output expressions without broadcast:c                 S   r*   r	   r+   r-   r	   r	   r   r      r   zGot input axis names:z:Got output axis names (excluding broadcasted output axes):c                 s       | ]}|j V  qd S r0   r'   r4   r	   r	   r   r5          c                 s   rw   r0   rx   r4   r	   r	   r   r5      ry   c                 3   &    | ]} |v r|  nd V  qd S r0   indexr   
axes_namesvr	   r   r5      s    
c                 3   rz   r0   r{   r}   r   r	   r   r5      s
    
zApplying backend.vmap to axis z, with input axis indices z and output axis indices z<All vmapped axes must appear in the output expression, but 'z' does not appear in ''c                 S   s(   |d u r| S | d | | |d d   S )Nr   r	   )r'   axisr	   r	   r   	drop_axis   s   zvmap_stage3.<locals>.drop_axisc                 3       | ]
\}} ||V  qd S r0   r	   r   r'   r   r   r	   r   r5      r6   c                 3   r   r0   r	   r   r   r	   r   r5      s    
zNow has remaining input axes z and output axes )in_axesout_axesinput_shapesoutput_shapesz 
Sending shapes to backend.vmap:c                 S   s   g | ]}t |jqS r	   )r,   r'   rB   r	   r	   r   r     s    c                 s   s    | ]
}t j|jV  qd S r0   r<   r4   r	   r	   r   r5     r6   )r>   rH   zGot overall flat tensor_out:c                    s(   g | ]\}}}t j||| d d qS )r#   r   )r   transpose_broadcast)r   expr_out_wbr(   r_   r#   r	   r   r     s    z/Got overall transposed+broadcasted tensors_out:rO   z$Got overall unflattened tensors_out:c                 S   r?   r	   r@   rB   r	   r	   r   r     rD   )rJ   rX   rW   allrN   r$   r)   r2   ConcatenationrZ   all_to_tensorrR   r   r\   r   rj   appendrV   reversedrv   vmapr%   rI   r'   rA   rS   )r   r   r   r   r   r    r   r!   rn   r)   exprs_in_flatexprs_out_flataxes_names_inru   vmapped_axes exprs_out_flat_without_broadcast axes_names_out_without_broadcastvmapsr   r   r   r   out_axisr_   r~   tensorsr(   r	   )rs   r   r   r   rc   rd   re   rf   r   rt   r   r   r!   r   vmap_stage3	   s4  


$R







	
r   T)csec                O   s  t jj| |\} }t jj| }t|dkr&t jj|d |d 	 g}t|d t|kr@t
dt|d  dt| t jjdd t|d |D dd |d D  dd | D  |d	d
d t|d t|d   }|d t|d  |t|d d  }}||fS )Nr   r   r"   z input tensors, but got c                 S   s   g | ]\}}t j||qS r	   r$   r)   Equation)r   expr_intensor_shaper	   r	   r   r   4  s    zparse.<locals>.<listcomp>c                 S      g | ]}t j|qS r	   r   )r   r_   r	   r	   r   r   8      c                 S   s4   g | ]\}}t jj|t|d tjf dddqS ).N)depth1depth2)r$   r)   r   npasarraynewaxis)r   kr   r	   r	   r   r   9  s    "F)r   
cse_concat)r$   r    r   !_clean_description_and_parametersr)   stage1parse_oprJ   Op__deepcopy__rX   solverZ   items)descriptionr   tensor_shapes
parametersr    exprsr   r   r	   r	   r   parse!  s8   
 	*r   c                    r   )Nc                    s$    | gfdd|D R i |S )Nc                    r   r	   r	   r
   r   r	   r   r   H  r   r   r	   )r   r   r   r   r	   r   r   G  s    r   r	   r   r	   r   r   r   G  r   )r   r   r   r   r   r   r    r   r   r   r   r   c          
   	   O   sZ   t | gdd |D R d|i|\}}	t|||	||||d\}}	t|	dkr+|d S |S )aY	  Vectorizes and applies a function to the input tensors using automatic vectorization.

    The function ``op`` must accept input tensors and yield output tensors as specified in
    ``description`` with shapes matching the subexpressions that are marked with ``[]``-brackets.

    Args:
        description: Description string for the operation in einx notation.
        tensors: Input tensors or tensor factories matching the description string.
        op: Function that will be vectorized. If ``op`` is a string, retrieves the attribute
            of ``backend`` with the same name.
        flat: Whether to pass the tensors to ``op`` in flattened form or matching the nested
            layout in the input expressions. Defaults to False.
        kwargs: Additional keyword arguments that are passed to ``op``. Defaults to ``{}``.
        backend: Backend to use for all operations. If None, determines the backend from the
            input tensors. Defaults to None.
        cse: Whether to apply common subexpression elimination to the expressions. Defaults
            to True.
        graph: Whether to return the graph representation of the operation instead of
            computing the result. Defaults to False.
        **parameters: Additional parameters that specify values for single axes,
            e.g. ``a=4``.

    Returns:
        The result of the vectorized operation if `graph=False`, otherwise the graph
        representation of the operation.

    Examples:
        Compute the mean along rows of a matrix:

        >>> x = np.random.uniform(size=(10, 8))
        >>> einx.vmap("a [b] -> a", x, op=np.mean)
        (10,)

        Vectorize a custom function:

        >>> x, y = (
        ...     np.random.uniform(size=(10, 13, 4)),
        ...     np.random.uniform(
        ...         size=(
        ...             4,
        ...             9,
        ...         )
        ...     ),
        ... )
        >>> def op(x, y): # c, d -> 2
        >>>     return np.stack([np.mean(x), np.max(y)])
        >>> einx.vmap("b1 [c] b2, b2 [d] -> b2 [2] b1", x, y, op=op).shape
        (4, 2, 10)

        Compute a matrix-matrix multiplication

        >>> x, y = (
        ...     np.random.uniform(size=(5, 10)),
        ...     np.random.uniform(size=(10, 3)),
        ... )
        >>> einx.vmap("a [b], [b] c -> a c", x, y, op=np.dot).shape
        (5, 3)
    c                 S   r   r	   )r$   r%   rA   )r   r(   r	   r	   r   r     r   zvmap.<locals>.<listcomp>r   )r   r   r    r   r   r   )r   r   rJ   )
r   r    r   r   r   r   r   r   r   r   r	   r	   r   r   E  s   J

r   )r$   	functools r   numpyr   typingr   r   r   numpy.typingnptjitr   	lru_cacher   traceback_utilfilterr,   r=   boolBackend	ArrayLiker   r	   r	   r	   r   <module>   sX    
  #	