
    ukim                        d dl mZ d dlmZmZ d dlZd dlmZ d dlZd dl	m
Z
 d dlmZ d dlmZmZ d dlmZ d d	lmZmZ d d
lmZ d dlmZ d ZddZ	 	 d	 ddZ	 	 d	 ddZ	 	 d	 	 	 ddZ	 	 d	 	 	 ddZeZy)    )annotations)CallableSequenceN)Any)core)	tree_util)_ensure_index_ensure_index_tuple)safe_zip)
split_listwraps)api_boundary)	JAXSparsec                "    t        | t              S N)
isinstancer   xs    U/home/cdr/jupyterlab/.venv/lib/python3.12/site-packages/jax/experimental/sparse/ad.py<lambda>r      s    jI.     c                    t        |      t        fdD              sJ t        j                  t              \  t        t        j                        j                         D cg c]  }|j                   c}      ^ }}|rJ t        t        j                  j                  fdt        |      D                    t        j                        \  }t        t        j                        j                         D cg c]  }|j                   c}      ^ }}|rJ t        |      D 	cg c]  \  }}	t	        |      r|	d d n|	 }}}	t        t        j                  j                  fdt        |      D                    }
 fd}fdfd}||
||fS c c}w c c}w c c}	}w )	Nc              3  P   K   | ]  }d |cxk  xr t              k  nc   yw)r   N)len).0argnumargss     r   	<genexpr>z,flatten_fun_for_sparse_ad.<locals>.<genexpr>$   s"     ?Q&$3t9$$?s   #&)is_leafc              3  2   K   | ]  \  }}|v s|  y wr    )r   inumsargnums_tups      r   r   z,flatten_fun_for_sparse_ad.<locals>.<genexpr>,   s#      5Hq$a;6Fd5H      c              3  2   K   | ]  \  }}|v s|  y wr   r!   )r   r"   r#   argnums_flat1s      r   r   z,flatten_fun_for_sparse_ad.<locals>.<genexpr>7   s#      5Jq$a=6Hd5Jr%   c                 h    t        j                  t        j                  |             } |i |S r   r   tree_unflatten)	args_flatkwargsr   funtree1tree2s      r   fun_flatz+flatten_fun_for_sparse_ad.<locals>.fun_flat:   s2    ##E9+C+CE9+UVDr   c                    t        j                  |          \  fd}t        |j                  d   j                  z
        D ]  }t	        j
                  |      }  ||      S )Nc                <    t        j                  | gdd        S )Nr&   r*   )gbufstrees    r   r   z@flatten_fun_for_sparse_ad.<locals>.reconstruct.<locals>.<lambda>@   s     11$T!"XG r   r   )r   tree_flattenrangendimjaxvmap)r"   grad_outf_recons_r5   r6   
args_flat1s       @@r   reconstructz.flatten_fun_for_sparse_ad.<locals>.reconstruct>   s^    ''
16JD$GH8==47<</0 $(#h$Hr   c                    d gj                   z  }t        |       D ]  \  }} ||      ||<    t        j                  |      }t	        t        d |            }t        |      dk(  r|d   S |S )Nc                @    t         j                  j                  |       S r   )r:   r6   leavesr   s    r   r   zJflatten_fun_for_sparse_ad.<locals>.postprocess_gradients.<locals>.<lambda>J   s    sxxq'9 r   r&   r   )
num_leavesr   r   r+   tuplefilterr   )	grads_out
leaf_gradsr"   grad	grad_treer(   r@   r/   s        r   postprocess_gradientsz8flatten_fun_for_sparse_ad.<locals>.postprocess_gradientsE   s}    %***JM95 +4!!T*jm+((
;If99EFIy>Q.9Q<=I=r   )r
   allr   r7   	is_sparser   r8   rD   childrenlist	itertoolschainfrom_iterable	enumerater   rE   )r.   argnumsr   childleaf_argnums1endr,   leaf_argnums2argr#   argnums_flatr1   rK   r(   r$   r?   r@   r/   r0   s   ` `          @@@@@@r   flatten_fun_for_sparse_adr[   "   s   #G,+	?;?	??	?  ,,T9E*e"5)9)9#:BG..BR#SE$4$4#SU=#.y44 5H#M25H H I- ++J7)U"5)9)9#:BG..BR#SE$4$4#SU=#. %-Z$GI sD  )~4847 I- Iy44 5J#M25J J K, > 
<,A	AAG $T $TIs   3F3
F8
F=c                     t        j                   fd|}t        j                  t              t         |j                        t         fd              }|S )a"  Sparse-aware version of :func:`jax.value_and_grad`

  Arguments and return values are the same as :func:`jax.value_and_grad`, but when
  taking the gradient with respect to a :class:`jax.experimental.sparse` array, the
  gradient is computed in the subspace defined by the array's sparsity pattern.

  Examples:

    >>> from jax.experimental import sparse
    >>> X = sparse.BCOO.fromdense(jnp.arange(6.))
    >>> y = jnp.ones(6)
    >>> sparse.value_and_grad(lambda X, y: X @ y)(X, y)
    (Array(15., dtype=float32), BCOO(float32[6], nse=5))
  rT   has_auxdocstrrT   c                 z    t        	|       \  }}}} t        j                  |f|
d|| \  }}| ||      fS )Nr]   )r[   r:   value_and_grad)r   r-   r1   rZ   r,   rK   val_outr<   rT   r.   r^   s           r   value_and_grad_funz*value_and_grad.<locals>.value_and_grad_func   s^     @YY\^egk?l<HlI'<e**8e\SZe^degpqGX)(333r   )r:   rb   r   concrete_or_errorr	   r   __doc__r   )r.   rT   r^   r-   raw_value_and_grad_funrd   s   ```   r   rb   rb   P   sh      --c^7G^W]^""=':'+33WE4  F4 
r   c                     t        j                   fdi|}t        j                  t              t         |j                        t         fd              }|S )a  Sparse-aware version of :func:`jax.grad`

  Arguments and return values are the same as :func:`jax.grad`, but when taking
  the gradient with respect to a :class:`jax.experimental.sparse` array, the
  gradient is computed in the subspace defined by the array's sparsity pattern.

  Examples:

    >>> from jax.experimental import sparse
    >>> X = sparse.BCOO.fromdense(jnp.arange(6.))
    >>> y = jnp.ones(6)
    >>> sparse.grad(lambda X, y: X @ y)(X, y)
    BCOO(float32[6], nse=5)
  rT   r_   c                     t        |       \  }}}} t        j                  |f|	d|| }	r ||d         |d   fS  ||      S Nr]   r   r&   )r[   r:   rI   
r   r-   r1   rZ   r,   rK   outrT   r.   r^   s
          r   grad_funzgrad.<locals>.grad_fun   si     @YY\^egk?l<HlI'<
M#((8
M\7
Mf
My
YC"3q6*CF22 %%r   )r:   rI   r   re   r	   r   rf   r   )r.   rT   r^   r-   raw_grad_funrm   s   ```   r   rI   rI   l   s_      #9w9&9,""=':'\))7;&  <& 
/r   c                     t        j                   fdi|}t        j                  t              t         |j                        t         fd              }|S )aU  Sparse-aware version of :func:`jax.jacfwd`

  Arguments and return values are the same as :func:`jax.jacfwd`, but when taking
  the gradient with respect to a :class:`jax.experimental.sparse` array, the
  gradient is computed in the subspace defined by the array's sparsity pattern.
  Currently this is only implemented for dense outputs.
  rT   r_   c                     t        |       \  }}}} t        j                  |f|	d|| }	r ||d         |d   fS  ||      S rj   )r[   r:   jacfwdrk   s
          r   
jacfwd_funzjacfwd.<locals>.jacfwd_fun   j     @YY\^egk?l<HlI'<
O#**X
O|W
O
OQZ
[C"3q6*CF22 %%r   )r:   rq   r   re   r	   r   rf   r   )r.   rT   r^   r-   raw_jacfwd_funrr   s   ```   r   rq   rq      `     ::c=7=f=.""=':'^++W=&  >& 
r   c                     t        j                   fdi|}t        j                  t              t         |j                        t         fd              }|S )aU  Sparse-aware version of :func:`jax.jacrev`

  Arguments and return values are the same as :func:`jax.jacrev`, but when taking
  the gradient with respect to a :class:`jax.experimental.sparse` array, the
  gradient is computed in the subspace defined by the array's sparsity pattern.
  Currently this is only implemented for dense outputs.
  rT   r_   c                     t        |       \  }}}} t        j                  |f|	d|| }	r ||d         |d   fS  ||      S rj   )r[   r:   jacrevrk   s
          r   
jacrev_funzjacrev.<locals>.jacrev_fun   rs   r   )r:   rx   r   re   r	   r   rf   r   )r.   rT   r^   r-   raw_jacrev_funry   s   ```   r   rx   rx      ru   r   )rT   zint | tuple[int, ...]r   ztuple[Any, ...])r   F)r.   r   rT   int | Sequence[int]returnzCallable[..., tuple[Any, Any]])r.   r   rT   r{   r|   r   )r.   r   rT   r{   r^   boolr|   r   )
__future__r   collections.abcr   r   rP   typingr   r:   jax._srcr   r   jax._src.api_utilr	   r
   jax._src.utilr   r   r   jax._src.traceback_utilr   jax.experimental.sparse._baser   rM   r[   rb   rI   rq   rx   jacobianr!   r   r   <module>r      s    # .   
   @ " + 0 3 /	+B\ BC /M8 89%-< :; /7. :; /7. r   