Commit 40aa263a authored by Bastien Auvray's avatar Bastien Auvray
Browse files

Upload New File

parent d35edc1a
Loading
Loading
Loading
Loading

src/tests_swap.py

0 → 100644
+258 −0
Changes for src/tests_swap.py: 258 added lines, 0 removed lines.
Original line number Diff line number Diff line
import itertools

#Fonction outil pour calculer la parent distance.
#max_j(seq, i) trouve le plus grand entier j tq S[j] < S[i]
#et retourne j, ou retourne 0 si un tel j n'existe pas.
def max_j(seq, i):
    j = 0
    for k in range(0, i):
        if seq[k] < seq[i]:
            j = k + 1 #+1 pour la numérotation
    return j

#Parent-distance classique, lue de la gauche vers la droite.
def pdd(seq):
    res = []
    for i in range(len(seq)):
        j = max_j(seq, i)
        if j != 0:
            res.append(i + 1 - j) #+1 pour la numérotation
        else:
            res.append(0)
    return res

#Parent-distance de la droite vers la gauche, version paresseuse
#Il serait peut-être bon de la redéfinir comme pdd.
def pdg(seq):
    s = seq.copy()
    list.reverse(s)
    res = pdd(s)
    list.reverse(res)
    return res

#first_diff gauche et droite identifient la première position
#où les parent-distances diffèrent afin de mettre en évidence
#les deux indices sur lesquels le swap s'est possiblement produit.
#Chaque fonction renvoie l'indice de la première position qui diffère
#ou -1 si une telle position n'existe pas
def first_diff_d(pdd1, pdd2):
    for index, value in enumerate(zip(pdd1, pdd2)):
        if value[0] != value[1]:
            return index
    return -1

def first_diff_g(pdg1, pdg2):
    for index, value in reversed(list(enumerate(zip(pdg1, pdg2)))):
        if value[0] != value[1]:
            return index
    return -1


#Vérifie les conditions nécessaires (mais pas suffisantes)
#sur les éléments des parent-distances
#Voir pour factoriser le code plus tard
def check_abcd(pdd1, pdd2, pdg1, pdg2, i):
    ad = pdd1[i]
    bd = pdd1[i+1]
    cd = pdd2[i]
    dd = pdd2[i+1]
    ag = pdg1[i+1]
    bg = pdg1[i]
    cg = pdg2[i+1]
    dg = pdg2[i]
    #cas x[i] < x[i+1]
    if (bd == 1 and dg == 1):
        if ((ad == 0 and dd != 0)
        or (ad > 0 and (cd > ad or dd != ad + 1))
        or (bg == 0 and cg != 0)
        or (bg > 1 and cg != bg - 1)
        or (bg == 1)):
            return False
    #cas x[i] > x[i+1]
    if (bg == 1 and dd == 1):
        if ((ag == 0 and dg != 0)
        or (ag > 0 and (cg > ag or dg != ag + 1))
        or (bd == 0 and cd != 0)
        or (bd > 1 and cd != bd - 1)
        or (bd == 1)):
            return False
    #Tout est cohérent sinon
    return True

#Vérifie si seq2 peut être CT-équivalente (à un swap près) à seq1
def check_swap(seq1, seq2):
    pdd1 = pdd(seq1)
    pdd2 = pdd(seq2)
    pdg1 = pdg(seq1)
    pdg2 = pdg(seq2)
    i = first_diff_d(pdd1, pdd2)
    j = first_diff_g(pdg1, pdg2)
    if i == -1 or j == -1:
        return False
    diff = j - i
    if diff == 1:
        return check_abcd(pdd1, pdd2, pdg1, pdg2, i)
    if diff == -1:
        return check_abcd(pdd1, pdd2, pdg1, pdg2, j)
    if diff == 0:
        return (check_abcd(pdd1, pdd2, pdg1, pdg2, i-1)
                or check_abcd(pdd1, pdd2, pdg1, pdg2, i))
    return False

#Fonction outil qui onstruit la séquence '1..n' qui permet 
#d'ensuite générer toutes les permutations à l'aide d'itertools
def seq_n(n):
    res = ''
    for i in range(n):
        res += str(i+1)
    return res

#Brute force pour des permutations de taille n en effectuant 
#toutes les poignées de mains possibles, puis retourne
#le nombre de matchs d'après check_swap ainsi que le nombre de
#poignées de main
#Décommenter la partie sur res permet de retourner une liste de
#toutes les permutations qui ont match en plus
def check_all(n):
    perm = list(itertools.permutations(seq_n(n)))
    l = len(perm)
    check = 0
    handshake = 0
    #res = []
    for i in range(l):
        for j in range(i + 1, l):
            if check_swap(list(perm[i]), list(perm[j])):
                check += 1
                #res.append((i,j))
            handshake += 1
    return check, handshake#, res

#LEGACY CODE - USELESS AS OF NOW

# def check_swap_flag_or(seq1, seq2):
#     pdd1 = pdd(seq1)
#     pdd2 = pdd(seq2)
#     pdg1 = pdg(seq1)
#     pdg2 = pdg(seq2)
#     i = first_diff_d(pdd1, pdd2)
#     j = first_diff_g(pdg1, pdg2)
#     if i == -1 or j == -1:
#         return (False, False)
#     diff = j - i
#     if diff == 1:
#         return (check_abcd(pdd1, pdd2, pdg1, pdg2, i), False)
#     if diff == -1:
#         return (check_abcd(pdd1, pdd2, pdg1, pdg2, j), False)
#     if diff == 0:
#         return ((check_abcd(pdd1, pdd2, pdg1, pdg2, i-1)
#                 or check_abcd(pdd1, pdd2, pdg1, pdg2, i)), True)
#     return (False, False)

# def check_all_flag_or(n):
#     perm = list(itertools.permutations(seq_n(n)))
#     l = len(perm)
#     check = 0
#     handshake = 0
#     res = []
#     for i in range(l):
#         for j in range(i + 1, l):
#             ref = check_swap_flag_or(list(perm[i]), list(perm[j]))
#             if (ref == (True, True)):
#                 check += 1
#                 res.append((i+1,j+1))
#             handshake += 1
#     return check, handshake, res

# def check_swap_flag_xor(seq1, seq2):
#     pdd1 = pdd(seq1)
#     pdd2 = pdd(seq2)
#     pdg1 = pdg(seq1)
#     pdg2 = pdg(seq2)
#     i = first_diff_d(pdd1, pdd2)
#     j = first_diff_g(pdg1, pdg2)
#     if i == -1 or j == -1:
#         return (False, False)
#     diff = j - i
#     if diff == 1:
#         return (check_abcd(pdd1, pdd2, pdg1, pdg2, i), False)
#     if diff == -1:
#         return (check_abcd(pdd1, pdd2, pdg1, pdg2, j), False)
#     if diff == 0:
#         return ((check_abcd(pdd1, pdd2, pdg1, pdg2, i-1)
#                 ^ check_abcd(pdd1, pdd2, pdg1, pdg2, i)), True)
#     return (False, False)

# def check_all_flag_xor(n):
#     perm = list(itertools.permutations(seq_n(n)))
#     l = len(perm)
#     check = 0
#     handshake = 0
#     res = []
#     for i in range(l):
#         for j in range(i + 1, l):
#             ref = check_swap_flag_xor(list(perm[i]), list(perm[j]))
#             if (ref == (True, True)):
#                 check += 1
#                 res.append((i+1,j+1))
#             handshake += 1
#     return check, handshake, res

#-------------------------------------------

#TESTS

#list(itertools.permutations('012'))

#max_j(["5","6","1","3","4","2"], 4)
#max_j(('5','6','1','3','4','2'), 2)


#pdd(["4","5","6","1","2","7","8","3","9"])
#pdg(["4","5","6","1","2","7","8","3","9"])
#pdd(["4","5","6","3","1","7","8","2","9"])
#pdg(["4","5","6","3","1","7","8","2","9"])

#s1 = ["4","5","6","1","2","7","8","3","9"]
#s2 = ["4","5","6","3","1","7","8","2","9"]
#s3 = ("4","5","6","1","2","7","8","3","9")


#pd1 = pdd(s1)
#pd2 = pdd(s2)
#pd3 = pdg(s1)
#pd4 = pdg(s2)
#pd5 = pdd(s3)

#first_diff_d(pd1, pd2)
#first_diff_g(pd3, pd4)

#check_swap(s1, s2)
#check_swap(s1, s1)

#seq_n(3)

#list(itertools.permutations('1234'))

#l1 = check_all_flag_or(4)[2]
#l2 = check_all_flag_xor(4)[2]

#set(l1).symmetric_difference(set(l2))

#s4 = ["1","4","2","3"]
#s5 = ["3","2","1","4"]

#first_diff_d(pdd(s4), pdd(s5))
#first_diff_g(pdg(s4), pdg(s5))
#pdd(s4)
#pdd(s5)
#pdg(s4)
#pdg(s5)

#check_all_flag_or(4)
#check_all_flag_xor(4)

check_all(3)
check_all(4)
check_all(5)
check_all(6)
check_all(7)