Project: 061_REEF_Representation_Encoding_Fingerprints_for_Larg | Function: invariant_terms (iclr)

system: You are an expert Python programmer implementing algorithms from scientific papers.
Complete the masked function based on the algorithm description.
Follow Python best practices and maintain consistent code style.
Return **only** the complete Python function code.

user: Complete this Python function:

**DESCRIPTION:** Extracts invariant fingerprint terms from model weights by constructing matrices from attention and feedforward components. Implements the ICS (Invariant Cosine Similarity) baseline method for weight-based fingerprinting.

**KEY TERMS:** {
  "M_a": "attention invariant matrix X @ W_q @ W_k^T @ X^T",
  "M_b": "value-output invariant matrix X @ W_v @ W_o @ X^T",
  "M_f": "feedforward invariant matrix X @ W_up @ W_down @ X^T",
  "X_hat": "token embeddings",
  "invariant_terms": "concatenated flattened matrices"
}

**CONTEXT CODE:**         W_q = W_q @ C1
        W_k = W_k @ C1_inv
        W_v = W_v @ C1
        W_o = W_o @ C1_inv
        
    if attack_type == 'fnn':
        indices = torch.randperm(W_up.shape[-1])
        P_ffn = torch.eye(W_up.shape[-1])[indices].cuda()
        P_ffn_inv = torch.inverse(P_ffn).cuda()

        W_up = W_up @ P_ffn
        W_down = P_ffn_inv @ W_down
        
    if attack_type == 'embed':
        indices = torch.randperm(W_q.shape[-1])
        P_E = torch.eye(W_q.shape[-1])[indices].cuda()
        P_E_inv = torch.inverse(P_E).cuda()

        W_q = P_E_inv @ W_q
        W_k = P_E_inv @ W_k
        W_v = P_E_inv @ W_v
        W_o = W_o @ P_E
        W_up = P_E_inv @ W_up
        W_down = W_down @ P_E

    if attack_type == 'mix':
        n, m = W_q.shape[-1], W_up.shape[-1]
        
        C1 = torch.eye(n).cuda()
        perturbation = torch.normal(mean=0.0, std=0.01, size=(n, n)).cuda()
        C1 += perturbation.cuda()
        C1_inv = torch.inverse(C1).cuda()

        P_ffn = torch.eye(m)[torch.randperm(m)].cuda()
        P_ffn_inv = torch.inverse(P_ffn).cuda()
        
        P_E = torch.eye(n)[torch.randperm(n)].cuda()
        P_E_inv = torch.inverse(P_E).cuda()

        W_q = P_E_inv @ W_q @ C1
        W_k = P_E_inv @ W_k @ C1_inv
        W_v = P_E_inv @ W_v @ C1
        W_o = C1_inv @ W_o @ P_E
        W_up = P_E_inv @ W_up @ P_ffn
        W_down = P_ffn_inv @ W_down @ P_E
        X_hat = X_hat @ P_E
        

    return X_hat, W_q, W_k, W_v, W_o, W_up, W_down

def invariant_terms(model_tag, layers, do_attack=False, attack_type='att'):
    raise NotImplementedError("Function implementation has been masked for testing")

def cosine_similarity(tensor1, tensor2):
    cosine_similarity = 1 - cosine(tensor1.cpu().numpy(), tensor2.cpu().numpy())
    return cosine_similarity


def release():
    torch.cuda.empty_cache()
    gc.collect()


if __name__ == "__main__":
    layers = [30, 31]
    smodel_tag = 'llama-2-7b'
    s_vector = invariant_terms(smodel_tag, layers)

    tmodel_tags = [
        'llama-2-7b-chat', 'vicuna-7b-v1.5', 'tulu-2-7b', 'llama-2-coder-7b', 'llama-2-finance-7b',
        'chinese-llama-2-7b', 'Sheared-LLaMA-2.7B-ShareGPT', 'wizardmath-7b','llemma-7b','codellama-7b',
        'llama-3-8b','mistral-7b', 'baichuan-2-7b','internlm2-7b', 'qwen-7b-v1.5',
        'Sheared-LLaMA-2.7B-ShareGPT','Sheared-LLaMA-2.7B-Pruned','Sheared-LLaMA-2.7B',
        'Sheared-LLaMA-1.3B-ShareGPT','Sheared-LLaMA-1.3B-Pruned','Sheared-LLaMA-1.3B',
        # 'shisa-gamma-7b', 'wizardmath-7b-1.1', 'abel-7b-002'
        # 'openllama-2-7b', 'mpt-7b'
        'wandallama-2-7b', 'gblmllama-2-7b', 'sparsellama-2-7b',
    ]

    for tmodel_tag in tmodel_tags:
        if '1.3B' in tmodel_tag:
            layers = [22,23]
        t_vector = invariant_terms(tmodel_tag, layers)

        assert s_vector.size()[0] == t_vector.size()[0]
        cos_simi = cosine_similarity(s_vector, t_vector)
        print(f'ICS of {smodel_tag} and {tmodel_tag} is: {cos_simi}')

        release()

Complete the function implementation replacing "raise NotImplementedError".