o
    Ni&                     @   s  d dl Z d dlmZ d dlZdd Zdejdedejfdd	Zdejded
edejfddZ		d&dejdeded d
edejf
ddZ
	d'dejded dejfddZdejdejdejfddZdeej dejdejfddZdeej dejdedejfddZ	d'deej dejdeded dejf
d d!Zdeej dejdedejfd"d#Z	d'deej dejdeded dejf
d$d%ZdS )(    N)Literalc                 C   s(   |j d|  |    }||}|S )aI  
    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_shape r
   J/home/ubuntu/.local/lib/python3.10/site-packages/peft/utils/merge_utils.pyreshape_weight_task_tensors   s   
r   tensordensityreturnc                 C   sV   t | d}t||   }t j|  d|dd}d||d < | || j S )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_kr
   r
   r   magnitude_based_pruning%   s
   r   rescalec                 C   s2   t t j| |d}| | }|rt j||d |S )a  
    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_tensorr
   r
   r   random_pruning8   s
   r%   Fmethod)	magnituderandomc                 C   sj   |dkrt d| d | S |dk rtd| |dkr#t| |S |dkr.t| ||dS td	| )
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   r
   r
   r   pruneK   s   
r,   total)r-   	frequencyc                 C   s^   |   }|dkr| jdd}n|dkr|jdd}ntd| dt|dkdd}||kS )	aZ  
    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.
    r-   r   r   r.   zUnimplemented mask method ""r   r   )signsumRuntimeErrorr   where)r   r&   r1   sign_magnitudemajority_signr
   r
   r   calculate_majority_sign_maskg   s   r7   r   majority_sign_maskc                 C   s.   | | j dd}|j dd}|tj|dd S )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   r/   g      ?)min)r2   r   clamp)r   r8   mixed_task_tensorsnum_params_preservedr
   r
   r   disjoint_merge   s   r=   r   c                 C   s0   t j| dd} t| |}| | }|jdd}|S )a  
    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   r/   r   stackr   r2   )r   r   weighted_task_tensorsr;   r
   r
   r   task_arithmetic   s
   
rA   c                    B    fdd| D } t j| dd} t| |}| | }|jdd}|S )aX  
    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.
    c                       g | ]	}t | d dqS r'   r&   r,   .0r   r   r
   r   
<listcomp>       z#magnitude_prune.<locals>.<listcomp>r   r/   r>   r   r   r   r@   r;   r
   rI   r   magnitude_prune      
rM   majority_sign_methodc                    L    fdd| D } t j| dd} t| |d}t| |}| | }t||}|S )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.
    c                    rC   rD   rF   rG   rI   r
   r   rJ      rK   zties.<locals>.<listcomp>r   r/   rE   r   r?   r7   r   r=   r   r   r   rO   r8   r@   r;   r
   rI   r   ties      

rS   c                    rB   )aS  
    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.
    c                       g | ]
}t | d ddqS r(   T)r&   r   rF   rG   rI   r
   r   rJ          zdare_linear.<locals>.<listcomp>r   r/   r>   rL   r
   rI   r   dare_linear   rN   rX   c                    rP   )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.
    c                    rU   rV   rF   rG   rI   r
   r   rJ     rW   zdare_ties.<locals>.<listcomp>r   r/   rE   rQ   rR   r
   rI   r   	dare_ties   rT   rY   )F)r-   )r)   typingr   r   r   Tensorfloatr   boolr%   r,   r7   r=   listrA   rM   rS   rX   rY   r
   r
   r
   r   <module>   sl   

 $
$ 