def pull_moves_mutation(protein,ind,mut_prob):
    ind_to_mut = deepcopy(ind[0])
    #we start applying the mutation from the end of the protein untill we reach the element 1, as the algorithm instructs 
    for i in range(len(ind_to_mut) - 2,0,-1):
        if random() < mut_prob:
            l_pos = find_l_pos(i, ind_to_mut)
            if l_pos in ind_to_mut:
                continue
            c_pos = find_c_pos(i, ind_to_mut,l_pos)
            if c_pos == ind_to_mut[i-1]:
                ind_to_mut[i] = l_pos
            elif c_pos not in ind_to_mut:
                ind_to_mut[i] = l_pos
                ind_to_mut[i - 1] = c_pos
                ind_to_mut = repair_conformation(i,ind_to_mut,ind[0])
    if check_ind_validity(ind_to_mut) == False:
        return (ind[0],fitness_function(protein,ind[0]))
    return (ind_to_mut,fitness_function(protein,ind_to_mut))
def evaluate_ind(protein,ind):
    return fitness_function(protein,ind[0])