
    oi&                     |   S SK r S SKJr  S SKrS rS\R
                  S\S\R
                  4S jrS\R
                  S\S\S\R
                  4S	 jr	 SS\R
                  S\S
\S   S\S\R
                  4
S jjr
 SS\R
                  S
\S   S\R
                  4S jjrS\R
                  S\R
                  S\R
                  4S jrS\\R
                     S\R
                  S\R
                  4S jrS\\R
                     S\R
                  S\S\R
                  4S jr SS\\R
                     S\R
                  S\S\S   S\R
                  4
S jjrS\\R
                     S\R
                  S\S\R
                  4S jr SS\\R
                     S\R
                  S\S\S   S\R
                  4
S jjrg)    N)Literalc                     UR                   SU R                  5       UR                  5       -
  -  -   nUR                  U5      nU$ )a-  
Reshapes `weights` to match the shape of `task_tensors` by unsqeezing in the remaining dimenions.

Args:
    task_tensors (`torch.Tensor`): The tensors that will be used to reshape `weights`.
    weights (`torch.Tensor`): The tensor to be reshaped.

Returns:
    `torch.Tensor`: The reshaped tensor.
)   )shapedimview)task_tensorsweights	new_shapes      P/home/james-whalen/.local/lib/python3.13/site-packages/peft/utils/merge_utils.pyreshape_weight_task_tensorsr      s>     (8(8(:W[[](J KKIll9%GN    tensordensityreturnc                 0   [         R                  " U 5      R                  S5      n[        XR	                  5       -  5      n[         R
                  " U R                  5       R                  S5      USS9nSX$S   '   XR                  U R                  5      -  $ )a>  
Prune the smallest values of the task tensors and retain the top-k values based on the specified fraction
`density`.

Args:
    tensor (`torch.Tensor`):The tensor to prune.
    density (`float`):The fraction of values to preserve. Should be in [0,1].

Returns:
    `torch.Tensor`: The tensor with the pruned weights.
T)klargestr   )torch
zeros_likereshapeintnumeltopkabsr   )r   r   maskr   top_ks        r   magnitude_based_pruningr   %   sv     F#++B/DGlln$%AJJvzz|++B/1dCEDqNLL...r   rescalec                     [         R                  " [         R                  " XS95      nX-  nU(       a  [         R                  " XAS9  U$ )aa  
Prune random values based on the specified fraction `density`.

Args:
    tensor (`torch.Tensor`):The tensor to prune.
    density (`float`):The fraction of values to preserve. Should be in [0,1].
    rescale (`bool`):Whether to rescale the result to preserve the expected value of the original tensor.

Returns:
    `torch.Tensor`: The pruned tensor.
)input
fill_value)r"   other)r   	bernoulli	full_likediv)r   r   r    r   pruned_tensors        r   random_pruningr)   8   s7     ??5??LMDMM		5r   method)	magnituderandomc                     US:  a  [         R                  " SU S35        U $ US:  a  [        SU 35      eUS:X  a  [        X5      $ US:X  a
  [	        XUS9$ [        S	U 35      e)
a  
Prune the values of task tensors based on the `method`.

Args:
    tensor (`torch.Tensor`):The tensor to prune.
    density (`float`):The fraction of values to preserve. Should be in [0,1].
    method (`str`):The method to use to prune. Should be one of ["magnitude", "random"].
    rescale (`bool`):Whether to rescale the result to preserve the expected value of the original tensor.

Returns:
    `torch.Tensor`: The pruned tensor.
r   zThe density z= is greater than or equal to 1, no pruning will be performed.r   zDensity should be >= 0, got r+   r,   )r    zUnknown method )warningswarn
ValueErrorr   r)   )r   r   r*   r    s       r   pruner1   K   sz     !|WI-jkl	17yABB&v77	8	fw???6(344r   )total	frequencyc                     U R                  5       nUS:X  a  U R                  SS9nO%US:X  a  UR                  SS9nO[        SU S35      e[        R                  " US:  SS5      nX$:H  $ )	a>  
Get the mask of the majority sign across the task tensors. Task tensors are stacked on dimension 0.

Args:
    tensor (`torch.Tensor`):The tensor to get the mask from.
    method (`str`):The method to use to get the mask. Should be one of ["total", "frequency"].

Returns:
    `torch.Tensor`: The majority sign mask.
r2   r   r   r3   zUnimplemented mask method ""r   r   )signsumRuntimeErrorr   where)r   r*   r7   sign_magnitudemajority_signs        r   calculate_majority_sign_maskr=   g   ss     ;;=D*	;	a8BCCKK! 3Q;M  r   r	   majority_sign_maskc                 r    X-  R                  SS9nUR                  SS9nU[        R                  " USS9-  $ )a  
Merge the task tensors using disjoint merge.

Args:
    task_tensors (`torch.Tensor`):The task tensors to merge.
    majority_sign_mask (`torch.Tensor`):The mask of the majority sign across the task tensors.

Returns:
    `torch.Tensor`: The merged tensor.
r   r5   g      ?)min)r8   r   clamp)r	   r>   mixed_task_tensorsnum_params_preserveds       r   disjoint_mergerD      sF     ';@@Q@G-11a18,@c JJJr   r
   c                 l    [         R                  " U SS9n [        X5      nX-  nUR                  SS9nU$ )z
Merge the task tensors using `task arithmetic`.

Args:
    task_tensors(`List[torch.Tensor]`):The task tensors to merge.
    weights (`torch.Tensor`):The weights of the task tensors.

Returns:
    `torch.Tensor`: The merged tensor.
r   r5   )r   stackr   r8   )r	   r
   weighted_task_tensorsrB   s       r   task_arithmeticrH      sA     ;;|3L),@G(2.22q29r   c           	          U  Vs/ s H  n[        X2SS9PM     n n[        R                  " U SS9n [        X5      nX-  nUR	                  SS9nU$ s  snf )a8  
Merge the task tensors using `task arithmetic`.

Args:
    task_tensors(`List[torch.Tensor]`):The task tensors to merge.
    weights (`torch.Tensor`):The weights of the task tensors.
    density (`float`): The fraction of values to preserve. Should be in [0,1].

Returns:
    `torch.Tensor`: The merged tensor.
r+   r*   r   r5   r1   r   rF   r   r8   r	   r
   r   r   rG   rB   s         r   magnitude_prunerM      sd     NZZ\6E&+>\LZ;;|3L),@G(2.22q29 [s   Amajority_sign_methodc           	          U  Vs/ s H  n[        XBSS9PM     n n[        R                  " U SS9n [        XS9n[	        X5      nX-  n[        Xe5      nU$ s  snf )a  
Merge the task tensors using `ties`.

Args:
    task_tensors(`List[torch.Tensor]`):The task tensors to merge.
    weights (`torch.Tensor`):The weights of the task tensors.
    density (`float`):The fraction of values to preserve. Should be in [0,1].
    majority_sign_method (`str`):
        The method to use to get the majority sign mask. Should be one of ["total", "frequency"].

Returns:
    `torch.Tensor`: The merged tensor.
r+   rJ   r   r5   r1   r   rF   r=   r   rD   r	   r
   r   rN   r   r>   rG   rB   s           r   tiesrR      sg    ( NZZ\6E&+>\LZ;;|3L5l`),@G(2'(=R [s   Ac           
          U  Vs/ s H  n[        X2SSS9PM     n n[        R                  " U SS9n [        X5      nX-  nUR	                  SS9nU$ s  snf )a3  
Merge the task tensors using `dare linear`.

Args:
    task_tensors(`List[torch.Tensor]`):The task tensors to merge.
    weights (`torch.Tensor`):The weights of the task tensors.
    density (`float`):The fraction of values to preserve. Should be in [0,1].

Returns:
    `torch.Tensor`: The merged tensor.
r,   Tr*   r    r   r5   rK   rL   s         r   dare_linearrU      sh     YeeXdfE&(DIXdLe;;|3L),@G(2.22q29 fs   Ac           
          U  Vs/ s H  n[        XBSSS9PM     n n[        R                  " U SS9n [        XS9n[	        X5      nX-  n[        Xe5      nU$ s  snf )a  
Merge the task tensors using `dare ties`.

Args:
    task_tensors(`List[torch.Tensor]`):The task tensors to merge.
    weights (`torch.Tensor`):The weights of the task tensors.
    density (`float`):The fraction of values to preserve. Should be in [0,1].
    majority_sign_method (`str`):
        The method to use to get the majority sign mask. Should be one of ["total", "frequency"].

Returns:
    `torch.Tensor`: The merged tensor.
r,   TrT   r   r5   rJ   rP   rQ   s           r   	dare_tiesrW      sk    ( YeeXdfE&(DIXdLe;;|3L5l`),@G(2'(=R fs   A)F)r2   )r.   typingr   r   r   Tensorfloatr   boolr)   r1   r=   rD   listrH   rM   rR   rU   rW    r   r   <module>r^      s<      /ELL /5 /U\\ /&5<< % $ 5<< ( ch5LL5#(529:O2P5[_5
\\5: CJ!LL!")*>"?!
\\!2K K5<< KTYT`T` K $u||"4 u|| PUP\P\ &$u||"4 u|| V[ `e`l`l 4 ;B	u||$\\  ""67	
 \\@d5<<0 5<< RW \a\h\h 4 ;B	u||$\\  ""67	
 \\r   